Spring boot wants @Component class to be @Bean in @Configuration class
When I test my @Component
class, spring boot tells me that this class must be declared as @Bean
in the @Configuration
class:
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.
code:
Main class:
@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 class:
@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
kind:
@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;
}
}
You don't show the package declaration in your code, but the error shows, AccountingSpringBootApplication
in the package org.accountingSpringBoot
, and Cryptography
in the package org.util
.
@SpringBootApplication
The package and sub-package components of the package are scanned in the classes that carry the annotations, i.e. the package org.accountingSpringBoot
.
Since it Cryptography
is encapsulated org.util
, it is not scanned, so it @Component
will not be visible to the Spring container.
you can:
move
Cryptography
to a subpackageorg.accountingSpringBoot
, e.g.org.accountingSpringBoot.util
Move
AccountingSpringBootApplication
to packageorg
(not recommended)Explicitly specify the packages to scan:
@SpringBootApplication(scanBasePackages={"org.accountingSpringBoot", "org.util"})
Rearrange your package structure.
I recommend this because your current package is too general, like:org.janlan.accounting.AccountingApplication org.janlan.accounting.util.Cryptography
Where
janlan
it could be your company name or your name, or something like that.
You should read the documentation on the recommended packaging structure for spring boot applications: Find the main application class