5

我正在学习 Spring Core 认证,我发现一些与代理概念相关的疑问。

因此,在学习材料中,我找到了以下测验:

有一个 Java配置类,其中包含以下方法:

@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() );
}

如您所见, transferService() 有 2 个不同的实现,分别命名为transferService1()transferService2(),它们创建并返回一个TransferServiceImpl对象。

第一个创建一个新的TransferServiceImpl对象,然后对其调用setAccountRepository()方法。

第二个简单地创建一个TransferServiceImpl,将一个新的JdbcAccountRepository对象传递给它的构造函数。

它问我**在前两种方法中哪个是最好的实现?

提供的答案是:Prefer call to dedicated method。所以我认为它说最好的方法是第一次实施。

它解释了AccountRepository bean 是一个单例(因为它是 Spring 中 bean 的标准范围)但是JdbcAccountRepository()可以被调用两次或更多次(例如在前面的代码片段中,它在调用方法时被调用transferService1()transferService2()如果是这样,这将是一个问题,因为AccountRepository必须是一个单例

这是真的吗?还是我错过了什么?

所以我收集到在启动时 foreach 配置类(用@Configuration注释)创建了一个扩展我的配置类的类。

例如,如果我有以下配置类:

@Configuration
public class AppConfig {
    @Bean public AccountRepository accountRepository() { ... }
    @Bean public TransferService transferService() { ... }
}

它会自动创建以下扩展我的AppConfig的类:

public class AppConfig$$EnhancerByCGLIB$ extends AppConfig {
    public AccountRepository accountRepository() { // ... }
    public TransferService transferService() { // ... }
    ...
    ...
    ...
}

所以子类是入口点(调用的方法是在子类中定义的方法),伪代码将是这样的:

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

所以很清楚 Spring 如何处理单例问题:它调用扩展配置类的代理类上的方法,如果请求的 bean 存在于 applicationContext 中,则返回此 bean,否则在创建的超类上调用相同的方法新 bean 并将其放入应用程序上下文中

这是基于代理模式的继承的正确含义还是我遗漏了什么?

4

1 回答 1

1

是的,您描述的基本上是Spring如何处理@Configuration

所有@Configuration类都在启动时使用 CGLIB 进行子类化。在子类中,子方法在调用父方法并创建新实例之前,首先检查容器中是否有任何缓存(作用域)bean。

如果认证问题中的问题是只有一个 的实例new JdbcAccountRepository(),那么,是的,最好使用类中的accountRepository() @Bean方法@Configuration

于 2014-11-14T19:00:16.813 回答