Java Bean light模式配置如何在Bean上创建代理

Java Bean light模式配置如何在Bean上创建代理,java,spring,spring-boot,Java,Spring,Spring Boot,我读了一部分关于@Bean Lite模式的spring文档 据我所知,如果config被注释为component,那么spring不会创建该config的代理类,并且该类中所有配置的bean都被视为普通方法调用。然而,根据这个例子,Spring为bean创建了代理,该bean被注释为@Transactional,并在@Component类中配置 @SpringBootApplication public class TranslatorApplication implements Command

我读了一部分关于@Bean Lite模式的spring文档 据我所知,如果config被注释为component,那么spring不会创建该config的代理类,并且该类中所有配置的bean都被视为普通方法调用。然而,根据这个例子,Spring为bean创建了代理,该bean被注释为@Transactional,并在@Component类中配置

@SpringBootApplication
public class TranslatorApplication implements CommandLineRunner {

    @Autowired
    ProxyBean bean;

    @Autowired
    Conf conf;

    public static void main(final String[] args) {
        SpringApplication.run(TranslatorApplication.class, args);
    }

    @Override
    public final void run(final String... args) {
        System.out.println(conf.getClass().getSimpleName());
        System.out.println(bean.getClass().getSimpleName());
    }

    @Component
    static class Conf {
        @Bean
        public ProxyBean bean() {
            return new ProxyBean();
        }
    }

    static class ProxyBean {

        @Transactional
        public void init() {

        }
    }
}
输出:

Conf
TranslatorApplication$ProxyBean$$EnhancerBySpringCGLIB$$f4c1a493
这意味着ProxyBean是由CGLIB创建的代理。 问题是,如果配置类不是代理,那么Spring如何为方法
公共ProxyBean()
创建代理? Spring Boot版本-2.1.6

我将尝试解释一下

若配置被注释为组件,那个么spring不会创建代理 此配置的类

Spring容器仅在需要时为bean创建代理,就像对bean的任何特殊处理一样,例如:AOP、事务管理。我已经为另一个SO问题解释了这一点,如果有兴趣,请浏览答案的A2部分

因此,例如,如果用
@Transactional
注释类,那么
Conf
类bean将是一个代理

此类中所有配置的bean都被视为普通方法 召唤

不对。Lite模式中的所有自调用或内部方法调用都是普通方法调用,而不是用
@Configuration
注释的类中的特殊处理。在
@Configuration
注释类中,对
@Bean
注释方法的多次调用返回相同的Bean实例

根据

与@Configuration中bean方法的语义不同 lite模式下不支持类“bean间引用”。 相反,当一个@Bean方法调用lite中的另一个@Bean方法时 模式,调用是标准的Java方法调用;春天 不通过CGLIB代理拦截调用。这类似于 事务间方法调用,而在代理模式下,Spring不调用 拦截调用-Spring仅在AspectJ模式下执行此操作

所以观察到

Spring为注释为@Transactional和@Transactional的bean创建了代理 在@Component类内部配置

原因一如预期

  • @Transactional
    注释的类需要代理
  • 在本例中,用
    @Component
    注释的类不需要任何特殊处理
  • 为了更好地解释这一点,我修改了您的示例

    值得注意的变化是

  • @Transactional
    注释
    @Component
    注释类以解释代理
  • 添加
    @Configuration
    类来解释“bean间引用”支持
  • 对于
    ConfigurationBean.init()
    方法,没有解释代理的
    @Transactional
  • 代码

    印刷品

    rg.xx.xx.TranslatorApplication$ComponentConf@8a589a2 : TranslatorApplication$ComponentConf$$EnhancerBySpringCGLIB$$e204f764
    rg.xx.xx.TranslatorApplication$ComponentBean@c65a5ef : TranslatorApplication$ComponentBean$$EnhancerBySpringCGLIB$$d3d05c88
    rg.xx.xx.TranslatorApplication$ComponentBean@6b5176f2 : TranslatorApplication$ComponentBean$$EnhancerBySpringCGLIB$$d3d05c88
    rg.xx.xx.TranslatorApplication$ConfigurationConf$$EnhancerBySpringCGLIB$$9369a982@b672aa8 : TranslatorApplication$ConfigurationConf$$EnhancerBySpringCGLIB$$9369a982
    rg.xx.xx.TranslatorApplication$ConfigurationBean@2fab4aff : ConfigurationBean
    rg.xx.xx.TranslatorApplication$ConfigurationBean@2fab4aff : ConfigurationBean
    
    请注意

  • ComponentConf
    bean被代理
  • ComponentBean
    由于Lite模式,返回两个不同的bean实例
  • ConfigurationBean
    返回相同的实例
  • ConfigurationBean
    实例未被代理
  • @kriegaex在
    @Configuration
    类的工作方面有一个很好的例子。一定要读书

    希望这有帮助。

    我会尽力解释

    若配置被注释为组件,那个么spring不会创建代理 此配置的类

    Spring容器仅在需要时为bean创建代理,就像对bean的任何特殊处理一样,例如:AOP、事务管理。我已经为另一个SO问题解释了这一点,如果有兴趣,请浏览答案的A2部分

    因此,例如,如果用
    @Transactional
    注释类,那么
    Conf
    类bean将是一个代理

    此类中所有配置的bean都被视为普通方法 召唤

    不对。Lite模式中的所有自调用或内部方法调用都是普通方法调用,而不是用
    @Configuration
    注释的类中的特殊处理。在
    @Configuration
    注释类中,对
    @Bean
    注释方法的多次调用返回相同的Bean实例

    根据

    与@Configuration中bean方法的语义不同 lite模式下不支持类“bean间引用”。 相反,当一个@Bean方法调用lite中的另一个@Bean方法时 模式,调用是标准的Java方法调用;春天 不通过CGLIB代理拦截调用。这类似于 事务间方法调用,而在代理模式下,Spring不调用 拦截调用-Spring仅在AspectJ模式下执行此操作

    所以观察到

    Spring为注释为@Transactional和@Transactional的bean创建了代理 在@Component类内部配置

    原因一如预期

  • @Transactional
    注释的类需要代理
  • 在本例中,用
    @Component
    注释的类不需要任何特殊处理
  • 为了更好地解释这一点,我修改了您的示例

    值得注意的变化是

  • @Transactional
    注释
    @Component
    注释类以解释代理
  • 添加
    @Configuration
    类来解释“bean间引用”支持
  • 对于
    ConfigurationBean.init()
    方法,没有解释代理的
    @Transactional
  • 代码

    印刷品

    rg.xx.xx.TranslatorApplication$ComponentConf@8a589a2 : TranslatorApplication$ComponentConf$$EnhancerBySpringCGLIB$$e204f764
    rg.xx.xx.TranslatorApplication$ComponentBean@c65a5ef : TranslatorApplication$ComponentBean$$EnhancerBySpringCGLIB$$d3d05c88
    rg.xx.xx.TranslatorApplication$ComponentBean@6b5176f2 : TranslatorApplication$ComponentBean$$EnhancerBySpringCGLIB$$d3d05c88
    rg.xx.xx.TranslatorApplication$ConfigurationConf$$EnhancerBySpringCGLIB$$9369a982@b672aa8 : TranslatorApplication$ConfigurationConf$$EnhancerBySpringCGLIB$$9369a982
    rg.xx.xx.TranslatorApplication$ConfigurationBean@2fab4aff : ConfigurationBean
    rg.xx.xx.TranslatorApplication$ConfigurationBean@2fab4aff : ConfigurationBean
    
    请注意

  • ComponentConf
    bean被代理
  • ComponentBean
    由于Lite模式,返回两个不同的bean实例
  • ConfigurationBean
    返回相同的实例
  • ConfigurationBean
    ar实例