我在这里阅读了spring文档中关于@Bean Lite模式的部分内容,根据我的理解,如果config被注释为component,那么spring就不会创建这个config的代理类,并且这个类中所有配置的bean都被视为普通方法调用。但是,根据这个示例,Spring为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如何为方法public ProxyBean bean()
创建代理?Spring Boot版本-2.1.6
我会试着解释
如果将config注释为component,则spring不会创建此config的代理类
Spring container仅在需要时才为bean创建代理,比如为bean的任何特殊处理(如AOP、事务管理)创建代理。我已经为另一个SO问题解释了这一点,如果有兴趣,请浏览答案的A2部分。
该类中所有配置的bean都被视为普通方法调用
不正确。Lite模式下的所有自调用或内部方法调用都是普通方法调用,与使用@configuration
注释的类中的特殊处理形成鲜明对比。在@configuration
注释类中,对@bean
注释方法的多次调用将返回同一个bean实例。
来自@bean的文档
是预期的原因
@transactional
注释的类需要代理@component
注释的类在此示例中不需要任何特殊处理我修改了你的例子以更好地解释这一点
@transactional
注释@component
注释类,以解释代理。@configuration
类来解释“bean间引用”支持configurationBean.init()
方法的@transactional
来解释代理。代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@SpringBootApplication
public class TranslatorApplication implements CommandLineRunner {
@Autowired
ComponentBean beanOne;
@Autowired
ComponentBean beanTwo;
@Autowired
ComponentConf conf;
@Autowired
ConfigurationBean beanThree;
@Autowired
ConfigurationBean beanFour;
@Autowired
ConfigurationConf config;
public static void main(final String[] args) {
SpringApplication.run(TranslatorApplication.class, args);
}
@Override
public final void run(final String... args) {
System.out.println(conf+" : "+conf.getClass().getSimpleName());
System.out.println(beanOne+" : "+beanOne.getClass().getSimpleName());
System.out.println(beanTwo+" : "+beanTwo.getClass().getSimpleName());
System.out.println(config+" : "+config.getClass().getSimpleName());
System.out.println(beanThree+" : "+beanThree.getClass().getSimpleName());
System.out.println(beanFour+" : "+ beanFour.getClass().getSimpleName());
}
interface ComponentConfIntf{}
@Component
@Transactional
static class ComponentConf{
@Bean
public ComponentBean beanOne() {
return new ComponentBean();
}
@Bean
public ComponentBean beanTwo() {
return beanOne();
}
}
static class ComponentBean {
@Transactional
public void init() {
}
}
@Configuration
static class ConfigurationConf {
@Bean
public ConfigurationBean beanThree() {
return new ConfigurationBean();
}
@Bean
public ConfigurationBean beanFour() {
return beanThree();
}
}
static class ConfigurationBean {
public void init() {
}
}
}
印刷品
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
对于@configuration
类的工作,@Kriegaex给出了一个很好的答案。一定要读。
希望这有帮助。
我想在Spring Boot应用程序的配置类中使用注释将定义为应用程序bean。 我正在调用我的应用流程中不同地方的4个rest服务。当前,我在每次请求时都创建。是否有一种方法可以使用将其定义为应用程序bean,并使用注入应用程序bean? 出现这个问题的主要原因是,我可以使用定义,但当我用注入它时,我会丢失所有已定义的拦截器(拦截器不会被调用。) 配置类 服务类别 看来我的在这种配置下根本没有被
我对单元测试有问题。下面是示例代码片段。我模拟了一个bean,并将其注入@configuration类,然后使用mocked属性创建另一个bean。 在下面的示例中,如果我检查,b.getSomething()会返回默认值,如字符串为“”,int为0等。我不会得到模拟值。你知道怎么做吗?
我正在创建JavaMailSender的bean类,并自动拥有javamailsender,但我得到错误 我不能为bean id="mail Sender"创建bean类。我在过去的两天里一直在努力,请让我离开它。 和错误页 组织。springframework。豆。工厂BeanCreationException:创建名为“employeeController”的bean时出错:自动连线依赖项的注
这是我的代码 这些是我得到的错误
问题内容: 我使用ektorp连接到CouchDB。 构建ektorp 实例的方法是使用构建器模式: 我对Spring比较陌生。请为我提供有关如何在上下文中配置以便通过进行创建的建议。 一种方法是使用。还有其他选择吗? 问题答案: 您可以尝试实现接口: 并添加到配置以下bean定义: 然后,您可以将此bean注入另一个bean,它将作为实例进行解析。
我正在尝试使用Java配置从头开始构建基于spring的应用程序,但我得到了一个我完全不理解的警告。。。有人能告诉我哪里出了什么问题吗? 错误:警告:上下文初始化期间遇到异常-正在取消刷新尝试组织。springframework。豆。工厂BeanCreationException:创建名为“applicationContext”的bean时出错:bean实例化失败;嵌套异常为org。springf