Spring Boot 希望 @Component 类成为 @Configuration 类中的 @Bean

Posted

技术标签:

【中文标题】Spring Boot 希望 @Component 类成为 @Configuration 类中的 @Bean【英文标题】:Spring Boot wants @Component class to be a @Bean in @Configuration class 【发布时间】:2019-10-08 06:32:15 【问题描述】:

当我测试我的@Component 类时,Spring boot 告诉我这个类应该在@Configuration 类中声明为@Bean

Field c in org.accountingSpringBoot.AccountingSpringBootApplication required a bean of type 'org.util.Cryptography' that could not be found.

The injection point has the following annotations:
    - @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'org.util.Cryptography' in your configuration.

代码:

主类:

@SpringBootApplication
public class AccountingSpringBootApplication implements CommandLineRunner 
    @Autowired
    ApplicationContext ctx;
    @Autowired
    Cryptography c;

    public static void main(String[] args) 
    SpringApplicationBuilder builder = new SpringApplicationBuilder(AccountingSpringBootApplication.class);
    builder.headless(false);

    ConfigurableApplicationContext context = builder.run(args);
    // SpringApplication.run(AccountingSpringBootApplication.class, args);

    

    @Override
    public void run(String... args) throws Exception 

    System.out.println(c.decrypt(c.encrypt("password")));
    


配置类:

@Configuration
@PropertySource("classpath:application.properties")
public class AppConfig 
    @Autowired
    private Environment env;

    @Bean
    @Scope(scopeName = "singleton")
    public SessionHandler sessionHandler() 
    return new SessionHandler();
    

    @Bean
    @Scope(scopeName = "singleton")
    public SessionFactory sessionFactory() 
    SessionFactory sessionFactory;
    try 
        sessionFactory = new org.hibernate.cfg.Configuration().configure().buildSessionFactory();
     catch (Throwable ex) 
        System.err.println("Initial SessionFactory creation failed." + ex);
        throw new ExceptionInInitializerError(ex);
    
    return sessionFactory;
    

    @Bean
    public SecretKey secretKey() 
    String secretKey = env.getProperty("crypto.secretkey");
    byte[] decodedKey = Base64.getDecoder().decode(secretKey);
    SecretKey originalKey = new SecretKeySpec(decodedKey, 0, decodedKey.length,
        env.getProperty("crypto.algorithm"));
    return originalKey;
    

@Component类:

@Component
public class Cryptography 
    @Autowired
    private SecretKey secretKey;
    private Cipher cipher; // = Cipher.getInstance("AES");

    public Cryptography() 
    try 
        System.out.println("hhhhh");
        this.cipher = Cipher.getInstance("AES");
     catch (NoSuchAlgorithmException | NoSuchPaddingException e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
    
    

    public String encrypt(String plainText) throws Exception 
    byte[] plainTextByte = plainText.getBytes();
    cipher.init(Cipher.ENCRYPT_MODE, secretKey);
    byte[] encryptedByte = cipher.doFinal(plainTextByte);
    Base64.Encoder encoder = Base64.getEncoder();
    String encryptedText = encoder.encodeToString(encryptedByte);
    return encryptedText;
    

    public String decrypt(String encryptedText) throws Exception 
    Base64.Decoder decoder = Base64.getDecoder();
    byte[] encryptedTextByte = decoder.decode(encryptedText);
    cipher.init(Cipher.DECRYPT_MODE, secretKey);
    byte[] decryptedByte = cipher.doFinal(encryptedTextByte);
    String decryptedText = new String(decryptedByte);
    return decryptedText;
    

【问题讨论】:

我看不到你的测试,但你的测试中有@SpringBootTest 吗?这样你就可以使用 SpringBootContextLoader 来创建你的 bean。 @GabLeg 通过测试我的意思是在run(String... args) 中调用decrypt()encrypt() 哦,我明白了,我的错!只是为了确定,你的包名是 org.util 吗?如果没有,您可能正在使用org.util.Cryptography 的外部库。确保导入您的 Cryptography 类。 是的,我的包名是org.util——这个类是我自己实现的 【参考方案1】:

您没有使用默认应用布局,因此您的 org.util.Cryptography 类未被发现。

有几种可能的解决方案

使用@ComponentScan 使用默认包布局。检查Locating the Main Application Class 从 Cryptography 类中删除 @Component(无论如何都没有发现它)。在返回 Cryptography 实例的配置类中声明一个使用 @Bean 注释的方法。 (您的配置类使用这种方法和一些 bean)

【讨论】:

【参考方案2】:

您没有在代码中显示包声明,但错误显示AccountingSpringBootApplication 在包org.accountingSpringBoot 中,而Cryptography 在包org.util 中。

@SpringBootApplication 启用对带有注解的类的包和子包的组件扫描,即包org.accountingSpringBoot

由于Cryptography在包org.util中,所以不会被扫描,所以Spring容器看不到@Component

你可以:

Cryptography 移动到org.accountingSpringBoot 的子包中,例如org.accountingSpringBoot.util

AccountingSpringBootApplication 移动到包装org (不推荐)

明确指定要扫描的包:

@SpringBootApplication(scanBasePackages="org.accountingSpringBoot", "org.util")

重新安排你的包结构。我推荐这个,因为你当前的包太通用了,例如:

org.janlan.accounting.AccountingApplication
org.janlan.accounting.util.Cryptography

janlan 可以是您的公司名称、您的姓名或类似名称。

您应该阅读有关 Spring Boot 应用程序的推荐包结构的文档:Locating the Main Application Class

【讨论】:

以上是关于Spring Boot 希望 @Component 类成为 @Configuration 类中的 @Bean的主要内容,如果未能解决你的问题,请参考以下文章

spring boot: 一般注入说明 @Component, application event事件为Bean与Bean之间通信提供了支持

Spring Boot在单元测试时删除@Component

Spring boot之SpringApplicationBuilder,@@Configuration注解,@Component注解

Spring Boot 之注解@Component @ConfigurationProperties(prefix = "sms")

jar文件的spring boot parent

如果删除过滤器类中的@component,则不会调用 Spring Boot 过滤器