如何准确地工作基于 Spring 继承的代理配置?

And*_*ili 5 java spring design-patterns proxy-pattern applicationcontext

我正在学习 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() );
}
Run Code Online (Sandbox Code Playgroud)

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

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

第二个只是创建一个TransferServiceImpl将一个新的JdbcAccountRepository对象传递给它的构造函数。

它问我**前两种方法的最佳实现是什么?

提供的答案是:首选调用专用方法。所以我认为它说最好的方法是第一个实现。

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

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

因此,我认为在启动时为每个配置类(用@Configuration注释)创建了一个扩展我的配置类的类。

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

@Configuration
public class AppConfig {
    @Bean public AccountRepository accountRepository() { ... }
    @Bean public TransferService transferService() { ... }
}
Run Code Online (Sandbox Code Playgroud)

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

public class AppConfig$$EnhancerByCGLIB$ extends AppConfig {
    public AccountRepository accountRepository() { // ... }
    public TransferService transferService() { // ... }
    ...
    ...
    ...
}
Run Code Online (Sandbox Code Playgroud)

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

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
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

Sot*_*lis 1

是的,你所描述的基本上就是Spring 处理@Configuration类的方式

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

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