Bean的创建流程

Bean的创建流程

总流程

  1. 启动applicationContext
  2. 创建BeanFactory
  3. 初始化BeanFactory
  4. 执行BeanFactory后置处理器
  5. 进行扫描
  6. 生成BeanDefinition
  7. 合成BeanDefinition
  8. 加载类
  9. 实例化前
  10. 推断构造方法
  11. 实例化
  12. BeanDefintion后置处理方法
  13. 实例化后
  14. 填充属性
  15. 填充属性后
  16. 执行Aware
  17. 初始化前
  18. 初始化
  19. 初始化后

1:生成BeanDefinition

Spring启动的时候会进行扫描,会先调用 org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#scanCandidateComponents(String basePackage)扫描某个包路径,并且得到BeanDefintion的Set集合

  1. 首先通过对ResourdePatternResolver获得指定包路径下的所有.class文件(Spring源码中将此文件包装成了Resource对象)
  2. 遍历每一个Resource对象
  3. 利用MatadataReaderFactor解析Resource对象得到MetadataReader(在Spring源码中MetadataReaderFactory具体的实现类为CachingMetadataReaderFactory,MetadataReader的具体实现类为SimpleMetadataReade)
  4. 利用MetadataReader进行excludeFilters和includeFilters,以及条件注解@Conditional的筛选(条件注解并不能理解:某个类上是否存在@Conditional注解,如果存在则调用注解中所指定的类的match方法进行匹配,匹配成功则通过筛选,匹配失败则pass掉。)
  5. 筛选通过后,基于metadataReader生成ScannedGenericBeanDefinition
  6. 再基于metadataReader判断是不是对应的类是不是接口或抽象类
  7. 如果筛选通过,那么就表示扫描到了一个Bean,将ScannedGenericBeanDefinition加入结果集

MetadataReader表示类的元数据读取器,主要包含了一个AnnotationMetadata,功能有

2:合并BeanDefinition

 通过扫描得到所有BeanDefinition之后,就可以根据BeanDefinition创建Bean对象了,但是在Spring
 中支持父子BeanDefinition,和Java父子类类似,但是完全不是一回事。父子BeanDefinition
 实际用的比较少,使用是这样的,比如:
<bean id="parent" class="com.zhouyu.service.Parent" scope="prototype"/>
<bean id="child" class="com.zhouyu.service.Child"/>

这么定义的情况下,child是单例Bean。

<bean id="parent" class="com.zhouyu.service.Parent" scope="prototype"/>
<bean id="child" class="com.zhouyu.service.Child" parent="parent"/>

但是这么定义的情况下,child就是原型Bean了。
因为child的父BeanDefinition是parent,所以会继承parent上所定义的scope属性。
​而在根据child来生成Bean对象之前,需要进行BeanDefinition的合并,得到完整的child的BeanDefinition。

就是说,这个bean的创建需要和他的父类的属性进行合并。然后需要进行BeanDefinition合并得到完整的BeanDefinition。

3加载类

BeanDefinition 合并之后,就可以去创建Bean对象了,而创建Bean就必须实例化对象,而实例化对象就必须先加载当前BeanDefinition所对应的class,在AbstractAutowireCapableBeanFactory类的createBean()方法中,一开始就会调用:

	Class<?> resolvedClass = resolveBeanClass(mbd, beanName);

这行代码就是去加载类,该方法是这么实现的:

if (mbd.hasBeanClass()) {
 return mbd.getBeanClass();
}
if (System.getSecurityManager() != null) {
 return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) () ->
  doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
 }
else {
 return doResolveBeanClass(mbd, typesToMatch);
}

public boolean hasBeanClass() {
 return (this.beanClass instanceof Class);
}

如果Beanclass属性的类型是class,那么就直接返回,如果不是,则会根据类名进行加载(doResolveBeanClass方法所做的事情)
会利用BeanFactory所设置的类加载器进行加载,如果没有设置,则默认使用**ClassUtils.getDefaultClassLoader()**所返回的类加载器进行加载。
ClassUtils.getDefaultClassLoader()

  1. 优先返回当前线程的类加载器(ClassLoader)
  2. 线程中类加载器为null的情况下,返回classUtils类的类加载器
  3. 如果ClassUtils类的类加载器为空,那么表示Bootstrap类加载器加载的ClassUtils类,那么则返回系统类加载器

4实例化前

当前BeanDefinition对应的类成功加载后,就可以实例化对象了

在spring中实例化对象之前,spring提供了一个亮点,允许用户控制是否在某个或者某些Bean实例化前启动一些动作,这个扩展点叫做InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()。比如

@Component
public class ZhouyuBeanPostProcessor 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 ZhouyuBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

 @Override
 public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
  if ("userService".equals(beanName)) {
   System.out.println("实例化前");
   return new UserService();
  }
  return null;
 }
}

userServeice这个Bean,在实例化前会直接返回一个有我们自己定义的对象,如果是这样,表示不需要Spring来实例化了,并且后续的Spring依赖注入也不会进行了,会跳过这一步骤,只看杰之行初始化后这一步

5:实例化

在这个步骤中就会根据BeanDefinition去创建一个对象了。

5.1:Supplier创建对象

首先判断BeanDefinition是否设置了Supplier,如果设置了则调用Supplier的get()得到对象
的直接使用BeanDifinition对象来设置SUpplier,比如:

AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setInstanceSupplier(new Supplier<Object>() {
 @Override
 public Object get() {
  	return new UserService();
	 }
 });
context.registerBeanDefinition("userService", beanDefinition);
5.2: 工厂方法创建对象

如果没有设置Supplier,则检查BeanDefinition中是否设置了factoryMethod,也就是工厂方法,有两种方式可以设置factoryMethod,比如:

方式一:

<bean id="userService" class="com.zhouyu.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.zhouyu.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进行加工,比如:

@Component
public class ZhouyuMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {

 @Override
 public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
  if ("userService".equals(beanName)) {
   beanDefinition.getPropertyValues().add("orderService", new OrderService());
  }
 }
}

在Spring源码中,AutowiredAnnotationBeanPostProcessor就是一个MergedBeanDefinitionPostProcessor,它的postProcessMergedBeanDefinition()中会去查找注入点,并缓存在AutowiredAnnotationBeanPostProcessor对象的一个Map中(injectionMetadataCache)。

7. 实例化后

在处理完BeanDefinition后,Spring又设计了一个扩展点:InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation(),比如:

@Component
public class ZhouyuInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

 @Override
 public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {

  if ("userService".equals(beanName)) {
   UserService userService = (UserService) bean;
   userService.test();
  }

  return true;
 }
}

上述代码就是对userService所实例化出来的对象进行处理。
​这个扩展点,在Spring源码中基本没有怎么使用。

8. 自动注入

​9. 处理属性

这个步骤中,就会处理@Autowired、@Resource、@Value等注解,也是通过**InstantiationAwareBeanPostProcessor.postProcessProperties()**扩展点来实现的,比如我们甚至可以实现一个自己的自动注入功能,比如:

@Component
public class ZhouyuInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

 @Override
 public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
  if ("userService".equals(beanName)) {
   for (Field field : bean.getClass().getFields()) {
    if (field.isAnnotationPresent(ZhouyuInject.class)) {
     field.setAccessible(true);
     try {
      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 ZhouyuBeanPostProcessor 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 ZhouyuBeanPostProcessor 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

  1. InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
  2. 实例化
  3. MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()
  4. InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
  5. 自动注入
  6. InstantiationAwareBeanPostProcessor.postProcessProperties()
  7. Aware对象
  8. BeanPostProcessor.postProcessBeforeInitialization()
  9. 初始化
  10. BeanPostProcessor.postProcessAfterInitialization()
  • 13
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于Spring Bean的创建流程,我可以简单地给您介绍一下。 1. Spring容器读取Bean的定义,解析XML配置文件或者注解,获取Bean的信息。 2. Spring容器根据Bean的定义使用Java反射机制创建Bean实例。 3. Spring容器将Bean的属性值和其他Bean的引用注入到Bean实例中。 4. 如果Bean实现了BeanNameAware和BeanFactoryAware接口,Spring容器将Bean的ID和BeanFactory实例注入到Bean中。 5. 如果Bean实现了ApplicationContextAware接口,Spring容器将ApplicationContext实例注入到Bean中。 6. 如果Bean实现了BeanPostProcessor接口,Spring容器将调用BeanPostProcessor的postProcessBeforeInitialization方法对Bean进行预处理。 7. 如果Bean实现了InitializingBean接口,Spring容器将调用其afterPropertiesSet方法进行初始化。 8. 如果Bean在配置文件中使用了init-method属性或者使用了@PostConstruct注解,Spring容器将调用指定的初始化方法进行初始化。 9. 如果Bean实现了BeanPostProcessor接口,Spring容器将调用BeanPostProcessor的postProcessAfterInitialization方法对Bean进行后处理。 10. 当需要将Bean从容器中移除时,如果Bean实现了DisposableBean接口,Spring容器将调用其destroy方法进行销毁。 11. 如果Bean在配置文件中使用了destroy-method属性或者使用了@PreDestroy注解,Spring容器将调用指定的销毁方法进行销毁。 以上就是Spring Bean的创建流程,希望能对您有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值