Spring Bean 注册顺序优先级总结
总结Spring 相关知识点,根据日常开发遇到的问题进行整理总结
目录
Bean 注册优先级
- 具有
@ComponentScan
注解的bean优先注册 - 具有
@Configuration
注解的bean - 具有
@Controller @Service @Repository @Component
等常用注解的bean - 被
@Import
注解导入的Bean - 被 实现了
ImportSelector
接口的类导入的Bean - 被 实现了
ImportBeanDefinitionRegistrar
接口的类导入的Bean - 被
BeanDefinitionRegistry
动态注入的Bean (属于懒加载
,在没有被Spring进行getBean查找时,不会执行初始化方法)
Bean注册顺序
同一个级别的spring容器载入bean顺序是不确定的
,spring框架没有约定特定顺序逻辑规范。
但spring保证如果A依赖B (如beanA中有@Autowired B的变量),那么B将先于A被加载。
@DependsOn
如果A不依赖B,但是A需要在B后面初始化,可以使用@DependsOn(value=“Bbeanname”)。
B的@Bean上面需要手动指定Name,否则找不到。
@Order
@Order注解并不能改变Bean加载优先级
,不能指定 bean 的加载顺序
,
它适用于 AOP 的优先级
,以及将多个 Bean 注入到集合时,这些 bean 在集合中的顺序
@Bean 方法参数注入
@Configuration
public class MytestConfigure {
@Bean
public BeanA beanA(BeanB demoB){
System.out.println("bean A init");
return new BeanA();
}
@Bean
public BeanB beanB(){
System.out.println("bean B init");
return new BeanB();
}
}
上面的两个Bean加载到Spring容器时,Spring容器优先加载 BeanB
@AutoConfigureOrder
注解是Spring Boot提供
@AutoConfigureOrder 只能改变外部依赖的 @Configuration的顺序,例如 spring.factories中的@Configuration的顺序
@AutoConfigureBefore 和 @AutoConfigureAfter
注解是Spring Boot提供
@AutoConfigureBefore、@AutoConfigureAfter、@AutoConfigureOrder
这三个注解只能作用于自动配置类,而不能是自定义的@Configuration配置类
Bean初始化顺序问题
属性字段注入和构造器注入
如果bean直接依赖于另一个bean,我们可以将其通过属性字段或者构造函数参数引入进来。
而使用构造函数的方法显示依赖一个bean,能够保证·依赖的bean先初始化
。
private JdbcProperties prop;
public JdbcConfig(Jdbcproperties prop){
this.prop = prop;
}
但是属性注入不可以,属性注入是Spring等全部bean实例化之后进行的关系创建
,这种情况下,被注入的bean不一定优先创建
@Autowired
private JdbcProperties prop;
单一Bean 初始化执行方法顺序
- Bean对象的初始化方法; 初始化之后设置依赖的其他Bean
- 调用有
@PostConstruct
注解的方法; - 如果实现了
BeanNameAware
接口, 调用 setBeanName方法设置Bean的ID或者Name; - 如果实现了
BeanFactoryAware
接口, 调用 setBeanFactory方法设置BeanFactory; - 如果实现了
ApplicationContextAware
接口, 调用 setApplicationContext方法设置ApplicationContext; - 如果实现了
BeanPostProcessor
接口, 调用 BeanPostProcessor的预先初始化方法; - 如果实现了
InitializingBean
接口, 调用 InitializingBean的afterPropertiesSet方法; - 如果是
@Bean
方式注册,调用指定的init-method方法; - 如果实现了
BeanPostProcessor
接口, 调用 BeanPostProcessor的后初始化方法;
单一Bean 销毁时执行方法顺序
- 调用有
@PreDestroy
注解的方法; - 如果实现了
DisposableBean
接口, 调用 destroy方法; - 如果是
@Bean
方式注册,调用指定的destroyMethod方法;
BeanDefinition 解析
BeanDefinition 中包括属性、构造方法参数、依赖的 Bean 名称及是否单例、延迟加载等,Spring 根据 BeanDefinition 实例化 Bean.
参考博客: https://www.cnblogs.com/loongk/p/12262101.html
常见的 BeanDefinition 的接口类
AnnotatedBeanDefinition
用来操作注解元数据,一般通过注解方式(例如:@Component、@Bean)得到的 Bean。
AbstractBeanDefinition
是 BeanDefinition 的子抽象类,描述通用的 Bean定义。
RootBeanDefinition
继承自 AbstractBeanDefinition,它可以单独作为一个 BeanDefinition,也可以作为其他 BeanDefinition 的父类。
ChildBeanDefinition
该类继承自 AbstractBeanDefinition。其相当于一个子类,不可以单独存在,必须依赖一个父 BeanDetintion。
GenericBeanDefinition
是 ChildBeanDefinition 更好的替代者,它同样可以通过 setParentName 方法设置父 BeanDefinition。
下面三个 BeanDefinition 既实现了 AnnotatedBeanDefinition 接口,又间接继承 AbstractBeanDefinition 抽象类,这些 BeanDefinition 描述的都是注解形式的 Bean。
ConfigurationClassBeanDefinition
这个 BeanDefinition 用来描述在标注 @Configuration 注解的类中,通过 @Bean 注解实例化的 Bean
AnnotatedGenericBeanDefinition
该类继承自 GenericBeanDefinition ,并实现了 AnnotatedBeanDefinition 接口。这个 BeanDefinition 用来描述标注 @Configuration 注解的 Bean。
ScannedGenericBeanDefinition
该类继承自 GenericBeanDefinition ,并实现了 AnnotatedBeanDefinition 接口。这个 BeanDefinition 用来描述标注 @Component 注解的 Bean,其派生注解如 @Service、@Controller等。
关于 BeanFactoryPostProcessor和BeanPostProcessor 后置处理器
BeanFactoryPostProcessor:
BeanFactory 后置处理器,是对 BeanDefinition 对象进行修改
BeanPostProcessor:
Bean 后置处理器,是对生成的 Bean 对象进行修改
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition bd = beanFactory.getBeanDefinition("xxxxxxxBean");
System.out.println("得到了xxxxxxxBean 的BeanDefinition 定义 ");
MutablePropertyValues pv = bd.getPropertyValues();
if (pv.contains("userName")) {
pv.addPropertyValue("userName", "将在初始化时调用setUserName()方法修改remark");
}
}
}
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化方法之前的数据: " + bean.toString());
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化方法之后的数据:" + bean.toString());
return bean;
}
}
参考:https://www.jianshu.com/p/71e9b5dac4c4
值得注意的是:
实现了BeanPostProcessor 接口的类是特殊的,它们会被容器不同地对待。
所有实现了BeanPostProcessor 的Bean和它们直接引用的Bean都将被提前实例化(在其他AOP处理方法之前)
,因为Spring的AOP自动代理也是通过实现BeanPostProcessor接口来做的,所以 BeanPostProcessor的实现类和它们直接引用的bean不满足AOP自动代理的条件,因此它们导致AOP失效问题
。
更多推荐
所有评论(0)