spring中注入bean有几种方式,spring构造方法注入bean
00-1010简介构造方法依赖(推荐)@DependsOn(不推荐)BeanPostProcessor(不推荐)
目录
说明
本文介绍了Spring如何控制Bean注入的顺序。
首先需要注意的是,在bean中添加@Order(xxx)并不能控制bean注入的顺序!
控制bean的加载顺序的方法
1.构造方法依赖性
2.@DependsOn评论
3.BeanPostProcessor扩展
bean的初始化顺序和类加载的顺序基本相同:静态变量/语句块=实例变量或初始化语句块=构造方法=@Autowirebean注入顺序。
00-1010创建两个Bean,并要求在CDemo1之前初始化CDemo2。
@ component public class c demo 1 { private String name= c demo 1 ;public CDE mo 1(CDE mo 2 CDE mo 2){ system . out . println(name);} } @ component public class c demo 2 { private String name= c demo 2 ;public c c demo 2(){ system . out . println(name);}}结果(如预期)
限制
如果存在注入关系,比如:通过构造方法将CDemo2注入到CDemo1中,那么在两个没有注入关系的bean之间指定优先级是不合适的(比如我想让一个bean在所有其他bean初始化之前执行)。
循环依赖,比如上面CDemo2的构造方法,如果有一个参数是CDemo1,那么就会产生循环依赖,无法启动应用。
还有一点需要注意的是,构造方法中不能有复杂耗时的逻辑,会拖慢应用的启动时间。
00-1010为什么不推荐:该方法通过bean的名称(字符串)控制顺序。如果您更改bean的类名,您可能会忘记更改所有使用它的注释,这是一个大问题。
当一个bean在另一个bean实例化后需要实例化时,可以使用该注释。
@ depends on( right demo 2 )@ component public class right demo 1 { private String name= right demo 1 ;public right demo 1(){ system . out . println(name);} } @ component public class right demo 2 { private String name= right demo 2 ;public right demo 2(){ system . out . println(name);}}上面的注释是在RightDemo1上解放的,说明RightDemo1的初始化依赖于bean rightDemo2。
可以控制bean的实例化顺序,但是不能保证bean的初始化顺序(比如构造bean实例后调用@PostConstruct注释的初始化方法)。例如,下面的例子可以说明这个问题。
@ depends on( right demo 2 )@ component public class right demo 1 { private String name= right demo 1 ;@ Autowired private right demo 2 right demo 2;public right demo 1(){ system . out . println(name);} @ post construct public void init(){ system . out . println(name _ init );} } @ component public class right demo 2 { private String name= right demo 2 ;@ Autowired private right demo 1 right demo 1;公共权利Demo2()
{ System.out.println(name); } @PostConstruct public void init() { System.out.println(name + " _init"); }}结果(先实例的Bean反而在后边执行init)
把上面测试代码中的@Autowired的依赖注入删除,即两个bean没有相互注入依赖,再执行,会发现输出顺序又不一样
BeanPostProcessor(不推荐)
一种非典型的使用方式,如非必要,请不要用这种方式来控制bean的加载顺序。
场景1:希望HDemo2在HDemo1之前被加载
@Componentpublic class HDemo1 { private String name = "h demo 1"; public HDemo1() { System.out.println(name); }} @Componentpublic class HDemo2 { private String name = "h demo 2"; public HDemo2() { System.out.println(name); }}
@Componentpublic class DemoBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements BeanFactoryAware { private ConfigurableListableBeanFactory beanFactory; @Override public void setBeanFactory(BeanFactory beanFactory) { if (!(beanFactory instanceof ConfigurableListableBeanFactory)) { throw new IllegalArgumentException( "AutowiredAnnotationBeanPostProcessor requires a ConfigurableListableBeanFactory: " + beanFactory); } this.beanFactory = (ConfigurableListableBeanFactory) beanFactory; } @Override @Nullable public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { // 在bean实例化之前做某些操作 if ("HDemo1".equals(beanName)) { HDemo2 demo2 = beanFactory.getBean(HDemo2.class); } return null; }}
将目标集中在postProcessBeforeInstantiation,这个方法在某个bean的实例化之前,会被调用,这就给了我们控制bean加载顺序的机会。
执行结果
场景2:希望某个bean在应用启动之后,首先实例化此Bean。
解决方法:重写DemoBeanPostProcessor的postProcessAfterInstantiation方法。
@Componentpublic class DemoBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements BeanFactoryAware { private ConfigurableListableBeanFactory beanFactory; @Override public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { if ("application".equals(beanName)) { beanFactory.getBean(FDemo.class); } return true; }} @DependsOn("HDemo")@Componentpublic class FDemo { private String name = "F demo"; public FDemo() { System.out.println(name); }} @Componentpublic class HDemo { private String name = "H demo"; public HDemo() { System.out.println(name); }}
执行结果(HDemo, FDemo的实例化顺序放在了最前面)
到此这篇关于一文详解Spring如何控制Bean注入的顺序的文章就介绍到这了,更多相关Spring控制Bean注入顺序内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。