Edit Fixed by changing package.
I have this configuration file for spring framework
@Configuration
public class AppConfig {
@Bean(initMethod = "populateCache")
public AccountRepository accountRepository(){
return new JdbcAccountRepository();
}
}
JdbcAccountRepository looks like this.
@Repository
public class JdbcAccountRepository implements AccountRepository {
@Override
public Account findByAccountId(long
return new SavingAccount();
}
public void populateCache() {
System.out.println("Populating Cache");
}
public void clearCache(){
System.out.println("Clearing Cache");
}
}
I'm new to spring framework and trying to use initMethod or destroyMethod. Both of these method are showing following errors.
Caused by: org.springframework.beans.factory.support.BeanDefinitionValidationException: Could not find an init method named 'populateCache' on bean with name 'accountRepository'
Here is my main method.
public class BeanLifeCycleDemo {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = new
AnnotationConfigApplicationContext(AppConfig.class);
AccountRepository bean = applicationContext.getBean(AccountRepository.class);
applicationContext.close();
}
}
Edit I was practicing from a book and had created many packages for different chapters. Error was it was importing different JdbcAccountRepository from different package that did not have that method. I fixed it and it works now. I got hinted at this from answers.
Like you said, if you are mixing configurations types, it can be confusing. Besides, even if you created a Bean of type AccountRepository
, because Spring does a lot of things at runtime, it can call your initMethod, even if the compiler couldn't.
So yes, if you have many beans with the same type, Spring can be confused an know which one to call, hence your exception.
Oh and by the way, having a Configuration
creating the accountRepoisitory
Bean
, you can remove the @Repository
from your JdbcAccountRepository
... It is either @Configuration + @Bean
or @Component/Repository/Service + @ComponentScan
.
TL;DR
Here is more information and how Spring creates your bean : What object are injected by Spring ?
@Bean(initMethod = "populateCache")
public AccountRepository accountRepository(){
return new JdbcAccountRepository();
}
With this code, Spring will :
- Detect that you want to add a Bean in the application Context
- The bean information are retrieved from the method signature. In your case, it will create a bean of type
AccountRepository
namedaccountRepository
... That's all Spring knows, it won't look inside your method body. - Once Spring is done analysing your classpath, or scanning the bean definitions, it will start instanciating your object.
- It will therefor creates your bean
accountRepository
of typeAccountRepository
. - But Spring is "clever" and nice with us. Even if you couldn't write this code without your compiler yelling at you, Spring can still call your method.
To make sure, try writing this code :
AccountRepository accountRepository = new JdbcAccountRepository();
accountRepository.populateCache(); // Compiler error => the method is not found.
But it works for Spring... Magic.
My recommandation, but you might thinking the same now: If you have classes across many packages to answer different business case, then rely on @Configuration
classes. @ComponentScan
is great to kickstart your development, but reach its limit when your application grows...