Spring Boot хочет, чтобы класс @Component был @Bean в классе @Configuration - PullRequest
3 голосов
/ 21 мая 2019

Когда я тестирую свой класс @Component, загрузка Spring сообщает, что этот класс должен быть объявлен как @Bean в @Configuration классе:

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;
    }
}

Ответы [ 3 ]

2 голосов
/ 21 мая 2019

Вы не показываете объявления пакета в своем коде, но ошибка показывает, что AccountingSpringBootApplication находится в пакете org.accountingSpringBoot, и что Cryptography находится в пакете org.util.

@SpringBootApplication включает компонентное сканирование пакета и подпакетов класса, содержащего аннотацию, т.е. пакета org.accountingSpringBoot.

Поскольку Cryptography находится в пакете org.util, он не сканируется, поэтому @Component не виден контейнером Spring.

Вы можете:

  • Переместить 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: Определение класса основного приложения

1 голос
/ 21 мая 2019

Вы не используете макет приложения по умолчанию, поэтому ваш класс org.util.Cryptography не обнаружен.

Существует несколько возможных решений

  • use @ComponentScan
  • использовать макет пакета по умолчанию.Отметьте Определение класса основного приложения
  • Удалите @Component из класса криптографии (он все равно не обнаружен).Объявите метод, аннотированный @Bean, в одном из ваших классов конфигурации, который возвращает экземпляр криптографии.(Ваш класс конфигурации использует этот подход с несколькими bean-компонентами)
0 голосов
/ 21 мая 2019

Вам нужно как-то рассказать вашему Configuration классу о вашем Cryptography классе.Один из вариантов - добавить следующий код в AppConfig class

@Bean
public Cryptography cryptography() {
    return new Cryptography()
}
...