总结Spring 相关知识点,根据日常开发遇到的问题进行整理总结
@ComponentScan
注解的bean优先注册@Configuration
注解的bean@Controller @Service @Repository @Component
等常用注解的bean@Import
注解导入的BeanImportSelector
接口的类导入的BeanImportBeanDefinitionRegistrar
接口的类导入的BeanBeanDefinitionRegistry
动态注入的Bean (属于懒加载
,在没有被Spring进行getBean查找时,不会执行初始化方法)同一个级别的spring容器载入bean顺序是不确定的
,spring框架没有约定特定顺序逻辑规范。
但spring保证如果A依赖B (如beanA中有@Autowired B的变量),那么B将先于A被加载。
如果A不依赖B,但是A需要在B后面初始化,可以使用@DependsOn(value=“Bbeanname”)。
B的@Bean上面需要手动指定Name,否则找不到。
@Order注解并不能改变Bean加载优先级
,不能指定 bean 的加载顺序
,
它适用于 AOP 的优先级
,以及将多个 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
注解是Spring Boot提供
@AutoConfigureOrder 只能改变外部依赖的 @Configuration的顺序,例如 spring.factories中的@Configuration的顺序
注解是Spring Boot提供
@AutoConfigureBefore、@AutoConfigureAfter、@AutoConfigureOrder
这三个注解只能作用于自动配置类,而不能是自定义的@Configuration配置类
如果bean直接依赖于另一个bean,我们可以将其通过属性字段或者构造函数参数引入进来。
而使用构造函数的方法显示依赖一个bean,能够保证·依赖的bean先初始化
。
private JdbcProperties prop;
public JdbcConfig(Jdbcproperties prop){
this.prop = prop;
}
但是属性注入不可以,属性注入是Spring等全部bean实例化之后进行的关系创建
,这种情况下,被注入的bean不一定优先创建
@Autowired
private JdbcProperties prop;
@PostConstruct
注解的方法; BeanNameAware
接口, 调用 setBeanName方法设置Bean的ID或者Name;BeanFactoryAware
接口, 调用 setBeanFactory方法设置BeanFactory;ApplicationContextAware
接口, 调用 setApplicationContext方法设置ApplicationContext; BeanPostProcessor
接口, 调用 BeanPostProcessor的预先初始化方法;InitializingBean
接口, 调用 InitializingBean的afterPropertiesSet方法;@Bean
方式注册,调用指定的init-method方法;BeanPostProcessor
接口, 调用 BeanPostProcessor的后初始化方法;@PreDestroy
注解的方法;DisposableBean
接口, 调用 destroy方法;@Bean
方式注册,调用指定的destroyMethod方法;BeanDefinition 中包括属性、构造方法参数、依赖的 Bean 名称及是否单例、延迟加载等,Spring 根据 BeanDefinition 实例化 Bean.
参考博客: https://www.cnblogs.com/loongk/p/12262101.html
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:
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失效问题
。