I am studying for the Spring Core certification and I am finding some doubts related to the proxying notion.
So on the study material I find the following quiz:
There is a Java configuration class that contains the following methods:
@Bean
public AccountRepository accountRepository(){
return new JdbcAccountRepository();
}
@Bean
public TransferService transferService1() {
TransferServiceImpl service = new TransferServiceImpl();
service.setAccountRepository(accountRepository());
return service;
}
@Bean
public TransferService transferService2() {
return new TransferServiceImpl( new JdbcAccountRepository() );
}
As you can see there are 2 different implementation of a transferService() respectively named as transferService1() and transferService2() that create and return a TransferServiceImpl object.
The first one creatre a new TransferServiceImpl object and then call the setAccountRepository() method on it.
The second one simply create a TransferServiceImpl passing a new JdbcAccountRepository object to its constructor.
It ask to me **Which is the best implementation brween the previous 2 methods?
And the answer provided is: Prefer call to dedicated method. So I think that it say that the best way is the first implementation.
It explain that AccountRepository bean is a singleton (because it is the standard scope for the beans in Spring) but that the JdbcAccountRepository() could be called twice or more times (for example in the previous code snippet it is called when are called the methods transferService1() and transferService2() and if so this would be a problem because AccountRepository have to be a singleton.
Is it true? Or am I missing something?
So I gather that at startup time foreach configuration class (annotated with @Configuration) is created a child class that extends my configuration class.
For example if I have the following configuration class:
@Configuration
public class AppConfig {
@Bean public AccountRepository accountRepository() { ... }
@Bean public TransferService transferService() { ... }
}
it is automatically created the following class that extends my AppConfig:
public class AppConfig$$EnhancerByCGLIB$ extends AppConfig {
public AccountRepository accountRepository() { // ... }
public TransferService transferService() { // ... }
...
...
...
}
So the child class is the entry point (the method called are those definied in the child class) and the pseudocode will be something like this:
public class AppConfig$$EnhancerByCGLIB$ extends AppConfig {
public AccountRepository accountRepository() {
// if bean is in the applicationContext return bean
// else call super.accountRepository() and store bean in context
}
public TransferService transferService() {
// if bean is in the applicationContext, return bean
// else call super.transferService() and store bean in context
}
}
So it appear pretty clear how Spring can handle the singleton problem: it call the methods on a proxy class that extends the configuration class and if the requested bean exist into the applicationContext return this beans, else call the same method on the super class that create the new bean and put it into the application context
Is it the right meaning of the inheritance based on the proxy pattern or am I missing something?
Yes, what you've described is basically how Spring handles @Configuration
classes
All
@Configuration
classes are subclassed at startup-time with CGLIB. In the subclass, the child method checks the container first for any cached (scoped) beans before it calls the parent method and creates a new instance.
If the problem in the certification question is to only have one instance of new JdbcAccountRepository()
, then, yes, it is best to use the accountRepository()
@Bean
method within the @Configuration
class.
来源:https://stackoverflow.com/questions/26935845/how-to-exactly-work-the-spring-inheritance-based-proxies-configuration