目录
ClassUtils.getDefaultClassLoader()
findCandidateComponents-->addCandidateComponentsFromIndex
addCandidateComponentsFromIndex
MergedBeanDefinitionPostProcessor
Spring最重要的功能就是帮助程序员创建对象(也就是IOC),而启动Spring就是为创建Bean对象做准备,所以我们先明白Spring到底是怎么去创建Bean的,也就是先弄明白Bean的生命周期。
Bean的生命周期就是指:在Spring中,一个Bean是如何生成的,如何销毁的。
Bean生命周期流程图:
Bean的生成过程
1. 生成BeanDefinition
Spring启动的时候会进行扫描,会先调用
org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#scanCandidateComponents(String basePackage)
扫描某个包路径,并得到BeanDefinition的Set集合。
Spring扫描的底层实现:
- 首先,通过ResourcePatternResolver获得指定包路径下的所有.class文件(Spring源码中将此文件包装成了Resource对象)
- 遍历每个Resource对象
- 利用MetadataReaderFactory解析Resource对象得到MetadataReader(在Spring源码中MetadataReaderFactory具体的实现类为CachingMetadataReaderFactory,MetadataReader的具体实现类为SimpleMetadataReader)
- 利用MetadataReader进行excludeFilters和includeFilters,以及条件注解@Conditional的筛选(条件注解并不难理解:某个类上是否存在@Conditional注解,如果存在则调用注解中所指定的类的match方法进行匹配,匹配成功则通过筛选,匹配失败则pass掉。)
- 筛选通过后,基于metadataReader生成ScannedGenericBeanDefinition
- 再基于metadataReader判断是不是对应的类是不是接口或抽象类
- 如果筛选通过,那么就表示扫描到了一个Bean,将ScannedGenericBeanDefinition加入结果集
MetadataReader表示类的元数据读取器,主要包含了一个AnnotationMetadata,功能有
- 获取类的名字、
- 获取父类的名字
- 获取所实现的所有接口名
- 获取所有内部类的名字
- 判断是不是抽象类
- 判断是不是接口
- 判断是不是一个注解
- 获取拥有某个注解的方法集合
- 获取类上添加的所有注解信息
- 获取类上添加的所有注解类型集合
值得注意的是,CachingMetadataReaderFactory解析某个.class文件得到MetadataReader对象是利用的ASM技术,并没有加载这个类到JVM。并且,最终得到的ScannedGenericBeanDefinition对象,beanClass属性存储的是当前类的名字,而不是class对象。(beanClass属性的类型是Object,它即可以存储类的名字,也可以存储class对象)
最后,上面是说的通过扫描得到BeanDefinition对象,还可以通过直接定义BeanDefinition,或解析spring.xml文件的<bean/>,或者@Bean注解得到BeanDefinition对象。
2. 合并BeanDefinition
通过扫描得到所有BeanDefinition之后,就可以根据BeanDefinition创建Bean对象了,但是在Spring中支持父子BeanDefinition,和Java父子类类似,但是完全不是一回事。
父子BeanDefinition实际用的比较少,使用是这样的,比如:
<bean id="parent" class="com.bubble.service.Parent" scope="prototype"/>
<bean id="child" class="com.bubble.service.Child"/>
这么定义的情况下,child是单例Bean。(如果之前未配置默认的单例作用域,则设置为默认的单例作用域。)
<bean id="parent" class="com.bubble.service.Parent" scope="prototype"/>
<bean id="child" class="com.bubble.service.Child" parent="parent"/>
但是这么定义的情况下,child就是原型Bean了。
因为child的父BeanDefinition是parent,所以会继承parent上所定义的scope属性。
而在根据child来生成Bean对象之前,需要进行BeanDefinition的合并,得到完整的child的BeanDefinition。
3. 加载类
BeanDefinition合并之后,就可以去创建Bean对象了,而创建Bean就必须实例化对象,而实例化就必须先加载当前BeanDefinition所对应的class,在AbstractAutowireCapableBeanFactory类的createBean()方法中,一开始就会调用:
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
这行代码就是去加载类,该方法是这么实现的:
// 如果BeanDefinition已经加载了beanClass,直接返回
if (mbd.hasBeanClass()) {
return mbd.getBeanClass();
}
// 检查是否启用了安全管理器
if (System.getSecurityManager() != null) {
// 使用特权访问模式执行bean类解析操作,以允许受限制的访问
return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) () ->
doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
}
else {
// 没有启用安全管理器,直接执行bean类解析操作
return doResolveBeanClass(mbd, typesToMatch);
}
-----------------------------------------------
public boolean hasBeanClass() {
// 检查beanClass是否已经被解析为Class类型
return (this.beanClass instanceof Class);
}
如果beanClass属性的类型是Class,那么就直接返回,如果不是,则会根据类名进行加载(doResolveBeanClass方法所做的事情)
会利用BeanFactory所设置的类加载器来加载类,如果没有设置,则默认使用ClassUtils.getDefaultClassLoader()所返回的类加载器来加载。
ClassUtils.getDefaultClassLoader()
- 优先返回当前线程中的ClassLoader
- 线程中类加载器为null的情况下,返回ClassUtils类的类加载器
- 如果ClassUtils类的类加载器为空,那么则表示是Bootstrap类加载器加载的ClassUtils类,那么则返回系统类加载器
4. 实例化前
当前BeanDefinition对应的类成功加载后,就可以实例化对象了,但是...
在Spring中,实例化对象之前,Spring提供了一个扩展点,允许用户来控制是否在某个或某些Bean实例化之前做一些启动动作。这个扩展点叫InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()。比如:
@Component
public class BubbleBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("实例化前");
}
return null;
}
}
如上代码会导致,在userService这个Bean实例化前,会进行打印。
值得注意的是,postProcessBeforeInstantiation()是有返回值的,如果这么实现:
@Component
public class BubbleBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("实例化前");
return new UserService();
}
return null;
}
}
userService这个Bean,在实例化前会直接返回一个由我们所定义的UserService对象。如果是这样,表示不需要Spring来实例化了,并且后续的Spring依赖注入也不会进行了,会跳过一些步骤,直接执行初始化后这一步。
5. 实例化
在这个步骤中就会根据BeanDefinition去创建一个对象了。
5.1 Supplier创建对象
首先判断BeanDefinition中是否设置了Supplier,如果设置了则调用Supplier的get()得到对象。
得直接使用BeanDefinition对象来设置Supplier,比如:
// 创建一个 AbstractBeanDefinition 对象,用于定义 bean 的元数据
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
// 设置 bean 的实例供应器,用于在需要时创建 UserService 实例
beanDefinition.setInstanceSupplier(new Supplier<Object>() {
@Override
public Object get() {
// 在实例供应器中创建并返回一个新的 UserService 实例
return new UserService();
}
});
// 将定义好的 bean 注册到 Spring 应用上下文中,使用 "userService" 作为 bean 的名称
context.registerBeanDefinition("userService", beanDefinition);
5.2 工厂方法创建对象
如果没有设置Supplier,则检查BeanDefinition中是否设置了factoryMethod,也就是工厂方法,有两种方式可以设置factoryMethod,比如:
方式一:
<bean id="userService" class="com.bubble.service.UserService" factory-method="createUserService" />
对应的UserService类为:
public class UserService {
public static UserService createUserService() {
System.out.println("执行createUserService()");
UserService userService = new UserService();
return userService;
}
public void test() {
System.out.println("test");
}
}
方式二:
<bean id="commonService" class="com.bubble.service.CommonService"/>
<bean id="userService1" factory-bean="commonService" factory-method="createUserService" />
对应的CommonService的类为:
public class CommonService {
public UserService createUserService() {
return new UserService();
}
}
Spring发现当前BeanDefinition方法设置了工厂方法后,就会区分这两种方式,然后调用工厂方法得到对象。
值得注意的是,我们通过@Bean所定义的BeanDefinition,是存在factoryMethod和factoryBean的,也就是和上面的方式二非常类似,@Bean所注解的方法就是factoryMethod,AppConfig对象就是factoryBean。如果@Bean所注解的方法是static的,那么对应的就是方式一。
5.3 推断构造方法
推断完构造方法后,就会使用构造方法来进行实例化了。
额外的,在推断构造方法逻辑中除开会去选择构造方法以及查找入参对象意外,会还判断是否在对应的类中是否存在使用@Lookup注解了方法。如果存在则把该方法封装为LookupOverride对象并添加到BeanDefinition中。
在实例化时,如果判断出来当前BeanDefinition中没有LookupOverride,那就直接用构造方法反射得到一个实例对象。如果存在LookupOverride对象,也就是类中存在@Lookup注解了的方法,那就会生成一个代理对象。
@Lookup注解就是方法注入,使用demo如下:
@Component
public class UserService {
private OrderService orderService;
public void test() {
OrderService orderService = createOrderService();
System.out.println(orderService);
}
@Lookup("orderService")
public OrderService createOrderService() {
return null;
}
}
6. BeanDefinition的后置处理
Bean对象实例化出来之后,接下来就应该给对象的属性赋值了。在真正给属性赋值之前,Spring又提供了一个扩展点MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition(),可以对此时的BeanDefinition进行加工,比如:
import org.springframework.stereotype.Component;
/**
* 自定义的 MergedBeanDefinition 后置处理器,用于在 bean 合并后对 bean 进行进一步处理。
*/
@Component
public class BubbleMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {
/**
* 在 bean 合并后的处理方法,用于对特定的 bean 进行进一步处理。
* @param beanDefinition 合并后的 RootBeanDefinition 对象,包含了合并后的 bean 元数据
* @param beanType bean 的类型,即 bean 的 Class 对象
* @param beanName bean 的名称
*/
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// 如果 bean 的名称是 "userService"
if ("userService".equals(beanName)) {
// 向 bean 的属性值中添加一个名为 "orderService" 的属性,并将一个新的 OrderService 实例作为属性值
beanDefinition.getPropertyValues().add("orderService", new OrderService());
}
}
}
在Spring源码中,AutowiredAnnotationBeanPostProcessor就是一个MergedBeanDefinitionPostProcessor,它的postProcessMergedBeanDefinition()中会去查找注入点,并缓存在AutowiredAnnotationBeanPostProcessor对象的一个Map中(injectionMetadataCache)。
7. 实例化后
在处理完BeanDefinition后,Spring又设计了一个扩展点:InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation(),比如:
//自定义的 InstantiationAwareBeanPostProcessor,用于在 bean 实例化之后对特定的 bean 进行处理。
@Component
public class BubbleInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
/**
* 在 bean 实例化之后的处理方法,用于对特定的 bean 进行进一步的处理。
* @param bean 实例化后的 bean 对象
* @param beanName bean 的名称
* @return 是否继续执行后续的 bean 初始化过程。返回 true 表示继续执行,返回 false 表示终止初始化过程。
* @throws BeansException 如果在处理过程中发生异常
*/
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
// 如果 bean 的名称是 "userService"
if ("userService".equals(beanName)) {
// 将 bean 强制转换为 UserService 类型,并调用其 test() 方法
UserService userService = (UserService) bean;
userService.test();
}
// 继续执行后续的 bean 初始化过程
return true;
}
}
上述代码就是对userService所实例化出来的对象进行处理。
这个扩展点,在Spring源码中基本没有怎么使用。
8. 自动注入
自动注入又分为两种:
- XML的autowire自动注入
- @Autowired注解的自动注入
8.1 XML的autowire自动注入
在XML中,我们可以在定义一个Bean时去指定这个Bean的自动注入模式:
- byType
- byName
- constructor
- default
- no
比如:
<bean id="userService" class="com.bubble.service.UserService" autowire="byType"/>
这么写,表示Spring会自动的给userService中所有的属性自动赋值(不需要这个属性上有@Autowired注解,但需要这个属性有对应的set方法)。
在创建Bean的过程中,在填充属性时,Spring会去解析当前类,把当前类的所有方法都解析出来,Spring会去解析每个方法得到对应的PropertyDescriptor对象,PropertyDescriptor中有几个属性:
- name:这个name并不是方法的名字,而是拿方法名字进过处理后的名字
- 如果方法名字以“get”开头,比如“getXXX”,那么name=XXX
- 如果方法名字以“is”开头,比如“isXXX”,那么name=XXX
- 如果方法名字以“set”开头,比如“setXXX”,那么name=XXX
- readMethodRef:表示get方法的Method对象的引用
- readMethodName:表示get方法的名字
- writeMethodRef:表示set方法的Method对象的引用
- writeMethodName:表示set方法的名字
- propertyTypeRef:如果有get方法那么对应的就是返回值的类型,如果是set方法那么对应的就是set方法中唯一参数的类型
get方法的定义是:方法参数个数为0个,并且 (方法名字以"get"开头 或者 方法名字以"is"开头并且方法的返回类型为boolean)
set方法的定义是:方法参数个数为1个,并且 (方法名字以"set"开头并且方法返回类型为void)
所以,Spring在通过byName的自动填充属性时流程是:
- 找到所有set方法所对应的XXX部分的名字
- 根据XXX部分的名字去获取bean
Spring在通过byType的自动填充属性时流程是:
- 获取到set方法中的唯一参数的参数类型,并且根据该类型去容器中获取bean
- 如果找到多个,会报错。
以上,分析了autowire的byType和byName情况,那么接下来分析constructor,constructor表示通过构造方法注入,其实这种情况就比较简单了,没有byType和byName那么复杂。
如果是constructor,那么就可以不写set方法了,当某个bean是通过构造方法来注入时,spring利用构造方法的参数信息从Spring容器中去找bean,找到bean之后作为参数传给构造方法,从而实例化得到一个bean对象,并完成属性赋值(属性赋值的代码得程序员来写)。
这里先不考虑一个类有多个构造方法的情况,我们这里只考虑只有一个有参构造方法。(多个构造方法-推断构造方法)
其实构造方法注入相当于byType+byName,普通的byType是根据set方法中的参数类型去找bean,找到多个会报错,而constructor就是通过构造方法中的参数类型去找bean,如果找到多个会根据参数名确定。
另外两个:
- no,表示关闭autowire
- default,表示默认值,我们一直演示的某个bean的autowire,而也可以直接在<beans>标签中设置autowire,如果设置了,那么<bean>标签中设置的autowire如果为default,那么则会用<beans>标签中设置的autowire。
可以发现XML中的自动注入是挺强大的,那么问题来了,为什么我们平时都是用的@Autowired注解呢?而没有用上文说的这种自动注入方式呢?
@Autowired注解相当于XML中的autowire属性的注解方式的替代。这是在官网上有提到的。
Essentially, the @Autowired annotation provides the same capabilities as described in Autowiring Collaborators but with more fine-grained control and wider applicability
本质上,@Autowired注解提供了与自动装配协作器中描述的相同的功能,但具有更细粒度的控制和更广泛的适用性
注意:更细粒度的控制。
XML中的autowire控制的是整个bean的所有属性,而@Autowired注解是直接写在某个属性、某个set方法、某个构造方法上的。
再举个例子,如果一个类有多个构造方法,那么如果用XML的autowire=constructor,你无法控制到底用哪个构造方法,而你可以用@Autowired注解来直接指定你想用哪个构造方法。
同时,用@Autowired注解,还可以控制,哪些属性想被自动注入,哪些属性不想,这也是细粒度的控制。
但是@Autowired无法区分byType和byName,@Autowired是先byType,如果找到多个则byName。
那么XML的自动注入底层其实也就是:
- set方法注入
- 构造方法注入
8.2 @Autowired注解的自动注入
上文说了@Autowired注解,是byType和byName的结合。
@Autowired注解可以写在:
- 属性上:先根据属性类型去找Bean,如果找到多个再根据属性名确定一个
- 构造方法上:先根据方法参数类型去找Bean,如果找到多个再根据参数名确定一个
- set方法上:先根据方法参数类型去找Bean,如果找到多个再根据参数名确定一个
而这种底层到了:
- 属性注入
- set方法注入
- 构造方法注入
@Component
public class UserService {
@Autowired
private OrderService orderService;
public void test(){
System.out.println("test---> "+orderService);
}
public void setOrderService(OrderService orderService) {
this.orderService = orderService;
}
}
//AppConfig.java
@Bean(autowire = Autowire.BY_NAME)
//@Bean(autowire = Autowire.BY_TYPE)
public UserService userService() {
UserService userService = new UserService();
return userService;
}
populateBean()方法中BY_NAME,BY_TYPE部分代码
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
// MutablePropertyValues是PropertyValues具体的实现类
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
// 根据名称自动装配属性值
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
// 根据类型自动装配属性值
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
9. 处理属性
这个步骤中,就会处理@Autowired、@Resource、@Value等注解,也是通过InstantiationAwareBeanPostProcessor.postProcessProperties()扩展点来实现的,比如我们甚至可以实现一个自己的自动注入功能,比如:
//自定义的 InstantiationAwareBeanPostProcessor,用于在 bean 实例化过程中对属性进行自定义注入操作。
@Component
public class BubbleInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
/**
* 在 bean 实例化过程中的属性处理方法,用于对特定的 bean 进行属性注入操作。
*
* @param pvs 原始的属性值集合
* @param bean 实例化后的 bean 对象
* @param beanName bean 的名称
* @return 修改后的属性值集合
* @throws BeansException 如果在处理过程中发生异常
*/
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
// 如果 bean 的名称是 "userService"
if ("userService".equals(beanName)) {
// 遍历 bean 类中的所有字段
for (Field field : bean.getClass().getFields()) {
// 判断字段上是否有 @BubbleInject 注解
if (field.isAnnotationPresent(BubbleInject.class)) {
// 设置字段可访问
field.setAccessible(true);
try {
// 使用反射为字段注入值 "123"
field.set(bean, "123");
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
// 返回修改后的属性值集合
return pvs;
}
}
10. 执行Aware
完成了属性赋值之后,Spring会执行一些回调,包括:
- BeanNameAware:回传beanName给bean对象。
- BeanClassLoaderAware:回传classLoader给bean对象。
- BeanFactoryAware:回传beanFactory给对象。
11. 初始化前
初始化前,也是Spring提供的一个扩展点:BeanPostProcessor.postProcessBeforeInitialization(),比如
@Component
public class BubbleBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("初始化前");
}
return bean;
}
}
利用初始化前,可以对进行了依赖注入的Bean进行处理。
在Spring源码中:
- InitDestroyAnnotationBeanPostProcessor会在初始化前这个步骤中执行@PostConstruct的方法,
- ApplicationContextAwareProcessor会在初始化前这个步骤中进行其他Aware的回调:
-
- EnvironmentAware:回传环境变量
- EmbeddedValueResolverAware:回传占位符解析器
- ResourceLoaderAware:回传资源加载器
- ApplicationEventPublisherAware:回传事件发布器
- MessageSourceAware:回传国际化资源
- ApplicationStartupAware:回传应用其他监听对象,可忽略
- ApplicationContextAware:回传Spring容器ApplicationContext
12. 初始化
- 查看当前Bean对象是否实现了InitializingBean接口,如果实现了就调用其afterPropertiesSet()方法
- 执行BeanDefinition中指定的初始化方法
13. 初始化后
这是Bean创建生命周期中的最后一个步骤,也是Spring提供的一个扩展点:BeanPostProcessor.postProcessAfterInitialization(),比如:
@Component
public class BubbleBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("初始化后");
}
return bean;
}
}
可以在这个步骤中,对Bean最终进行处理,Spring中的AOP就是基于初始化后实现的,初始化后返回的对象才是最终的Bean对象。
总结BeanPostProcessor
- InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
- 实例化
- MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()
- InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
- 自动注入
- InstantiationAwareBeanPostProcessor.postProcessProperties()
- Aware对象
- BeanPostProcessor.postProcessBeforeInitialization()
- 初始化
- BeanPostProcessor.postProcessAfterInitialization()
Bean的销毁过程
Bean销毁是发生在Spring容器关闭过程中的。
在Spring容器关闭时,比如:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) context.getBean("userService");
userService.test();
// 容器关闭
context.close();
在Bean创建过程中,在最后(初始化之后),有一个步骤会去判断当前创建的Bean是不是DisposableBean:
- 当前Bean是否实现了DisposableBean接口
- 或者,当前Bean是否实现了AutoCloseable接口
- BeanDefinition中是否指定了destroyMethod
- 调用DestructionAwareBeanPostProcessor.requiresDestruction(bean)进行判断
- ApplicationListenerDetector中直接使得ApplicationListener是DisposableBean
- InitDestroyAnnotationBeanPostProcessor中使得拥有@PreDestroy注解了的方法就是DisposableBean
- 把符合上述任意一个条件的Bean适配成DisposableBeanAdapter对象,并存入disposableBeans中(一个LinkedHashMap)
在Spring容器关闭过程时:
- 首先发布ContextClosedEvent事件
- 调用lifecycleProcessor的onCloese()方法
- 销毁单例Bean
- 遍历disposableBeans
- 把每个disposableBean从单例池中移除
- 如果这个disposableBean还包含了inner beans,将这些Bean从单例池中移除掉 (inner bean参考Redirecting...)
- 如果这个disposableBean还被其他Bean依赖了,那么也得销毁其他Bean
- 调用disposableBean的destroy()
- 清空manualSingletonNames,是一个Set,存的是用户手动注册的单例Bean的beanName
- 清空singletonBeanNamesByType,和allBeanNamesByType类似,只不过只存了单例Bean
- 清空allBeanNamesByType,是一个Map,key是bean类型,value是该类型所有的beanName数组
- 遍历disposableBeans
这里涉及到一个设计模式:适配器模式
在销毁时,Spring会找出实现了DisposableBean接口的Bean。
但是我们在定义一个Bean时,如果这个Bean实现了DisposableBean接口,或者实现了AutoCloseable接口,或者在BeanDefinition中指定了destroyMethodName,那么这个Bean都属于“DisposableBean”,这些Bean在容器关闭时都要调用相应的销毁方法。
所以,这里就需要进行适配,将实现了DisposableBean接口、或者AutoCloseable接口等适配成实现了DisposableBean接口,所以就用到了DisposableBeanAdapter。
会把实现了AutoCloseable接口的类封装成DisposableBeanAdapter,而DisposableBeanAdapter实现了DisposableBean接口。
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
// applicationContext.registerShutdownHook(); 使用这个或close()都是相同效果----------在JVM注册一个钩子
applicationContext.close();
// DisposableBean ....-->调用lifecycleProcessor的onCloese()方法
@Component
public class UserService implements DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("已销毁。。。");
}
}
// AutoCloseable....-->调用lifecycleProcessor的onCloese()方法
@Component
public class UserService implements AutoCloseable {
@Override
public void close() throws Exception {
System.out.println("已销毁。。。");
}
}
// @PreDestroy
@PreDestroy
public void close(){
System.out.println("已销毁。。。");
}
// setDecoratedDefinition
public class BeanFactoryPostTest implements MergedBeanDefinitionPostProcessor {
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
if ("userService".equals(beanName)) {
//匹配userService bean中的close(),如果没有close()方法就匹配shutdown()方法
beanDefinition.setDecoratedDefinition("(inferred)");
beanDefinition.setDecoratedDefinition("(a)");//匹配a()方法
}
}
}
注解&其他
@Conditional
加了@Conditional注解,UserService需要符合@Conditional(ConditionalTest.class)注解条件(ConditionalTest.matches())才能成为bean
/**
* 根据任意判断给定的类是否为候选组件
* {@code @Conditional} 注解。
* @param metadataReader 类的 ASM ClassReader
* @return 该类是否有资格作为候选组件
* 源码
*/
private boolean isConditionMatch(MetadataReader metadataReader) {
if (this.conditionEvaluator == null) {// 如果条件评估器为空,创建一个新的条件评估器
this.conditionEvaluator =
new ConditionEvaluator(getRegistry(), this.environment, this.resourcePatternResolver);
}
// 调用条件评估器的shouldSkip方法,判断是否应该跳过该类
// 如果返回false,表示该类符合条件,可以注册为Bean
return !this.conditionEvaluator.shouldSkip(metadataReader.getAnnotationMetadata());
}
//shouldSkip()方法会调用--> !condition.matches(this.context, metadata)--->ConditionalTest.matches
// 自定义方法
@Component
@Conditional(ConditionalTest.class)
public class UserService {
}
public class ConditionalTest implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
try {
context.getClassLoader().loadClass("com.bubble.service.User");//判断ClassLoader()是否有User类
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
}
独立类
@Component
public class UserService {
class Test66{}
}
@Lookup()
@Component
public class UserService {
@Autowired
private User user;
public void test() {
System.out.println(user);
}
}
@Component
@Scope("prototype")
public class User {
}
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) applicationContext.getBean("userService");
userService.test();
userService.test();
userService.test();
// 运行结果
com.bubble.service.User@71e7a66b
com.bubble.service.User@71e7a66b
com.bubble.service.User@71e7a66b
--->因为UserService只创建一次赋值一次,userService.test()用的同一个,即使User类加了@Scope("prototype"),但结果还是同一个
// 但是在UserService类中加上
@Lookup("user")//或@Lookup()
public User a(){
return null;
}
//运行结果
com.bubble.service.User@234bef66
com.bubble.service.User@737996a0
com.bubble.service.User@61dc03ce
findCandidateComponents-->addCandidateComponentsFromIndex
在spring.components中添加以下内容,还需要给对应的bean加上@Component注解,Spring扫描阶段就扫描spring.components中指定的内容,不需要扫描全部,可以提高效率。
addCandidateComponentsFromIndex
// 从候选组件索引中添加符合条件的候选组件定义到容器。
private Set<BeanDefinition> addCandidateComponentsFromIndex(CandidateComponentsIndex index, String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<>();// 存储符合条件的候选组件定义的集合
try {
Set<String> types = new HashSet<>();// 存储不同类型的扫描结果
for (TypeFilter filter : this.includeFilters) {
// Component注解,,// 遍历包含过滤器,提取注解的名称
String stereotype = extractStereotype(filter);
if (stereotype == null) {
throw new IllegalArgumentException("Failed to extract stereotype from " + filter);
}
// basePackage包路径,stereotype注解名字
types.addAll(index.getCandidateTypes(basePackage, stereotype));
}
// 判断日志级别是否为 TRACE 和 DEBUG
boolean traceEnabled = logger.isTraceEnabled();
boolean debugEnabled = logger.isDebugEnabled();
for (String type : types) {
// 获取类型的元数据读取器
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(type);
if (isCandidateComponent(metadataReader)) {
// 创建候选组件定义对象,并设置来源
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setSource(metadataReader.getResource());
if (isCandidateComponent(sbd)) {//bean定义是否有资格作为候选组件
if (debugEnabled) {
logger.debug("Using candidate component class from index: " + type);
}
candidates.add(sbd);// 将候选组件定义添加到集合中
}
else {
if (debugEnabled) {
logger.debug("Ignored because not a concrete top-level class: " + type);
}
}
}
else {
if (traceEnabled) {
logger.trace("Ignored because matching an exclude filter: " + type);
}
}
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
}
return candidates;// 返回包含候选组件定义的集合
}
applicationContext.getBean
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
//验证userService名,是否是对应的UserService.class这个类,,如果不是并且不能类型转换就会报错
UserService userService = applicationContext.getBean("userService", UserService.class);
//如果userService是原型bean,传参会调用有参数的构造方法,如果不是就还是调用默认无参构造方法
UserService userService = (UserService) applicationContext.getBean("userService",new UserService());
userService.test();
别名
// userService1.userService2是别名
@Bean({"userService","userService1",userService})
public UserService userService() {
UserService userService = new UserService();
return userService;
}
// userService2是别名
<bean id="userService" name="userService2" class="com.buble.service.UserService" />
// userService1.userService2是别名
<bean id="userService" class="com.example.MyBeanClass" />
<alias name="userService" alias="userService1" />
<alias name="userService" alias="userService2" />
// 使用aliasMap存别名
// aliasMap<"userService1","userService2">
// aliasMap<"userService2","userService">
private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);
public String canonicalName(String name) {
String canonicalName = name;
// Handle aliasing...
String resolvedName;
do {
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
@DependsOn
OrderService中加@DependsOn({userService})注解UserService中加@@DependsOn({OrderService}) 注解会报错,循环依赖
ClassLoader
Thread.currentThread().setContextClassLoader();
// 创建一个Spring容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
applicationContext.getBeanFactory().setBeanClassLoader();
@Override
public void setBeanClassLoader(@Nullable ClassLoader beanClassLoader) {
// 设置当前 bean 的类加载器,如果传入的 beanClassLoader 为 null,就使用默认类加载器
this.beanClassLoader = (beanClassLoader != null ? beanClassLoader : ClassUtils.getDefaultClassLoader());
}
//可以用于在解析 bean 类名时找到正确的类加载器,确保类能够正确地加载和实例化。如果没有显式地设置 bean 类加载器,就会使用默认的类加载器。
/** ClassLoader to resolve bean class names with, if necessary. */
@Nullable
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
@Nullable
public static ClassLoader getDefaultClassLoader() {
ClassLoader cl = null;
// 优先获取线程中的类加载器
try {
cl = Thread.currentThread().getContextClassLoader();
}
catch (Throwable ex) {
// Cannot access thread context ClassLoader - falling back...
}
// 线程中类加载器为null的情况下,获取加载ClassUtils类的类加载器
if (cl == null) {
// No thread context class loader -> use class loader of this class.
cl = ClassUtils.class.getClassLoader();
if (cl == null) {
// getClassLoader() returning null indicates the bootstrap ClassLoader
// 加入ClassUtils是被Bootstrap类加载器加载的,则获取系统类加载器
try {
cl = ClassLoader.getSystemClassLoader();
}
catch (Throwable ex) {
// Cannot access system ClassLoader - oh well, maybe the caller can live with null...
}
}
}
return cl;
}
//比如tomcat类加载器加载类,拿到自定义加载器加载器类(加载器名称不一样)
public class BeanPostProcessorTest1 implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Class<?> beanClass, String beanName) throws BeansException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
if ("userService".equals(beanName)) {
// 实例化前自己实例化,spring就不用实例化这个了
Object instance = beanClass.getConstructor().newInstance();
return instance;
}
return null;
}
}
实例化前实现了InstantiationAwareBeanPostProcessors(),重写了sss,返回User()对象,不继续往下执行了
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
return new User();
}
return null;
}
MergedBeanDefinitionPostProcessor
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) applicationContext.getBean("userService");
userService.test();
@Component
public class BubbleBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("加工beanFactory");
}
}
@Component
public class BubbleBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("初始化前"+bean);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("初始化后"+bean);
}
return bean;
}
}
@Component
public class BubbleuMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// 如果 bean 的名称是 "userService"
if ("userService".equals(beanName)) {
// 向 bean 的属性值中添加一个名为 "orderService" 的属性,并将一个新的 OrderService 实例作为属性值
// beanDefinition.getPropertyValues().add("orderService", new OrderService());
beanDefinition.setInitMethodName("aaa");
}
}
}
@Component
public class UserService {
public void aaa(){
System.out.println("test---> aaa ");
}
@Autowired
private OrderService orderService;
public void test(){
System.out.println("test---> "+orderService);
}
public void setOrderService(OrderService orderService) {
this.orderService = orderService;
}
}
// 运行结果
加工beanFactory
初始化前com.bubble.service.UserService@5d3411d
test---> aaa
初始化后com.bubble.service.UserService@5d3411d
test---> com.bubble.service.OrderService@6956de9
属性填充
实现InstantiationAwareBeanPostProcessor接口
调用protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {}方法
postProcessProperties-->@Autowired @Resource @Value() 处理这些注释
@Component
public class BubbleBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
// @Autowired @Resource @Value() 处理这些注释
// return InstantiationAwareBeanPostProcessor.super.postProcessProperties(pvs, bean, beanName);
}
}
BY_NAME,BY_TYPE
byType找出所有set方法,根据类型从容器找到对应的Bean,传给set方法
byname也是找set方法setOrderService,小写首字母,->orderService,把括号里的(数据)当作条件去容器。找到对应的bean,传给set方法
@Component
public class UserService {
@Autowired
private OrderService orderService;
public void test(){
System.out.println("test---> "+orderService);
}
public void setOrderService(OrderService orderService) {
this.orderService = orderService;
}
}
// 方式一
@Bean(autowire = Autowire.BY_NAME)
//@Bean(autowire = Autowire.BY_TYPE)
public UserService userService() {
UserService userService = new UserService();
return userService;
}
// 方式二
<context:annotation-config/>
<bean id="userService" class="com.bubble.service.UserService" autowire="byType"/>
populateBean()方法中部分代码
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
// MutablePropertyValues是PropertyValues具体的实现类
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
// 根据名称自动装配属性值
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
// 根据类型自动装配属性值
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}