Spring怎么创建Bean的生命周期(bean,spring,开发技术)

时间:2024-05-03 20:51:09 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

1.Bean 的创建生命周期

UserService.class &mdash;> 无参构造方法(推断构造方法) &mdash;> 普通对象 &mdash;> 依赖注入(为带有code>@Autowired</code的属性赋值) &mdash;> 初始化前(执行带有code>@PostConstruct</code的方法) &mdash;> 初始化(执行实现了InitializingBean接口的afterPropertiesSet方法) &mdash;> 初始化后(执行AOP相关逻辑) &mdash;> 代理对象 &mdash;> Bean

类似于:男孩 &mdash;> 依赖注入 &mdash;> 男人

大致过程如下:

  • 利用该类的构造方法来实例化得到一个对象(但是如何一个类中有多个构造方法,Spring 则会进行选择,这个叫做推断构造方法

  • 得到一个对象后,Spring 会判断该对象中是否存在被code>@Autowired</code注解了的属性,把这些属性找出来并由 Spring 进行赋值(依赖注入

  • 依赖注入后,Spring 会判断该对象是否实现了 BeanNameAware 接口、BeanClassLoaderAware接口、BeanFactoryAware 接口,如果实现了,就表示当前对象必须实现该接口中所定义的 setBeanName()setBeanClassLoader()setBeanFactory()方法,那么 Spring 就会调用这些方法并传入相应的参数(Aware回调

  • Aware 回调后,Spring 会判断该对象中是否存在某个方法被code>@PostConstruct</code注解了,如果存在,Spring 会调用当前对象的此方法(初始化前

  • 紧接着,Spring 会判断该对象是否实现了InitializingBean接口,如果实现了,就表示当前对象必须实现该接口中的afterPropertiesSet()方法,那么 Spring 就会调用当前对象中的afterPropertiesSet()方法(初始化

  • 最后,Spring 会判断当前对象需不需要进行 AOP,如果不需要那么Bean就创建完了,如果需要进行AOP,则会进行动态代理并生成一个代理对象作为Bean(初始化后

当Spring根据UserService类来创建一个Bean时:

  • 如果不用进行AOP,那么Bean就是UserService类的构造方法所得到的对象。

  • 如果需要进行AOP,那么Bean就是UserService的代理类所实例化得到的对象,而不是UserService本身所得到的对象。

Bean对象创建出来后:

  • 如果当前Bean是单例Bean,那么会把该Bean对象存入一个Map<String, Object>,Map的key为beanName,value为Bean对象。这样下次getBean时就可以直接从Map中拿到对应的Bean对象了。(实际上,在Spring源码中,这个Map就是单例池

  • 如果当前Bean是原型Bean,那么后续没有其他动作,不会存入一个Map,下次getBean时会再次执行上述创建过程,得到一个新的Bean对象。

推断构造方法:

    li><p>如果一个类里面有无参的构造方法,那么Spring默认就会用这个无参的构造方法。</p></li><li><p>如果一个类里面只有一个有参的构造方法,那么Spring就会用这个有参的构造方法。</p></li><li><p>如果一个类里面有多个有参的构造方法,并且没有无参的构造方法,那么Spring会报错。</p></li><li><p>如果想要指定Spring用哪个构造方法,可以在该构造方法上加<code>@Autowired</code/p></li></ul><p><code>@Bean</code会覆盖code>@Compoment</code

    注意:

    如果Spring选择了一个有参的构造方法,Spring在调用这个有参构造方法时,需要传入参数,那这个参数是怎么来的呢?

    Spring会根据入参的类型和入参的名字去Spring容器中找Bean对象(以单例Bean为例,Spring会从单例池的那个Map中去找):

    • 先根据入参类型找,如果只找到一个,那就直接用来作为入参

    • 如果根据类型找到多个,则再根据入参名字来确定唯一一个

    • 如果最终没有找到,则会报错,无法创建当前Bean对象

    确定用哪个构造方法,确定入参的Bean对象,这个过程就叫做推断构造方法

    2.Spring AOP 大致流程

    AOP就是进行动态代理,在创建一个Bean的过程中,Spring在最后一步会去判断当前正在创建的这个Bean是不是需要进行AOP,如果需要则会进行动态代理。

    如何判断当前Bean对象需不需要进行 AOP 操作:

    上面第三步找到匹配的之后,会将匹配的所有方法缓存起来,后面在执行切面方法的时候,可以快速从缓存中拿出来,提高执行效率。

    利用cglib进行AOP的大致流程:

    • 生成代理类UserServiceProxy,代理类继承UserService

    • 代理类中重写了父类的方法,比如UserService中的test()方法代理类中还会有一个target属性,该属性的值为被代理的对象(也就是通过UserService类推断构造方法实例化出来的对象,进行了依赖注入、初始化等步骤的对象)

    • 代理类中的test()方法被执行时的逻辑如下:

    当我们从Spring容器得到UserService的Bean对象时,拿到的就是UserServiceProxy所生成的对象,也就是代理对象。

    调用UserService代理对象.test( ) &mdash;> 执行切面逻辑 &mdash;> target.test( ),注意target对象不是代理对象,而是被代理的对象。

    UserServiceProxy(代理类)--->代理对象--->代理对象.target=普通对象
    代理对象.test();

    classUserServiceProxyextendsUserService{

    UserServicetarget;

    publicvoidtest(){
    //执行切面逻辑@Before-->从匹配的切面方法的缓存中拿出来

    target.test();//调用普通对象的test方法

    }

    }

    3.Spring 事务/h3><p>当我们在某个方法上加了<code>@Transactional</code注解后,就表示该方法在调用时会开启Spring事务,而这个方法所在的类所对应的Bean对象会是该类的代理对象

    Spring事务的代理对象执行某个方法时的步骤:

      li><p>判断当前执行的方法是否存在<code>@Transactional</code注解

    • 如果存在,则利用事务管理器(TransactionMananger)创建一个数据库连接

    • 修改数据库连接的 autocommit 为 false

    • 执行 target.test(),执行程序员所写的业务逻辑代码,也就是执行 sql/p></li><li><p>执行完了之后如果没有出现异常,则提交,否则回滚</p></li></ul><p>Spring事务是否会失效的判断标准:<strong>某个加了@Transactional注解的方法被调用时,要判断到底是不是直接被代理对象调用的,如果是则事务会生效,如果不是则会失效。</strong

      UserServiceProxy(代理类)--->代理对象--->代理对象.target=普通对象
      代理对象.test();

      classUserServiceProxyextendsUserService{

      UserServicetarget;

      publicvoidtest(){
      //1.先看看方法上面有没有加@Transactional
      //2.通过事务管理器dataSource,创建一个数据库连接conn
      //3.设置conn.autocommit=false,表示不自动提交事务

      target.test();//调用普通对象的test方法

      conn.commit();//如果方法都执行成功,那就手动提交事务
      conn.rollback();//如果某个方法执行失败,那就会回滚事务

      }

      }

      Spring怎么创建Bean的生命周期

      4.Spring 源码阅读前戏

      BeanDefinition

      BeanDefinition表示Bean定义,BeanDefinition中存在很多属性用来描述一个Bean的特点。

      比如:

      • class,表示Bean类型

      • scope,表示Bean的作用域,单例或原型等

      • lazyInit:表示Bean是否是懒加载

      • initMethodName:表示Bean初始化时要执行的方法

      • destroyMethodName:表示Bean销毁时要执行的方法还有很多&hellip;

      声明式定义 Bean:

      可以通过以下几种方式来定义Bean:

      也可以通过编程式定义 Bean

      AnnotationConfigApplicationContextcontext=newAnnotationConfigApplicationContext(AppConfig.class);

      //生成一个BeanDefinition对象,并设置beanClass为User.class,并注册到ApplicationContext中
      AbstractBeanDefinitionbeanDefinition=BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
      beanDefinition.setBeanClass(User.class);
      context.registerBeanDefinition("user",beanDefinition);

      System.out.println(context.getBean("user"));

      还可以通过BeanDefinition设置一个Bean的其他属性

      beanDefinition.setScope("prototype");//设置作用域
      beanDefinition.setInitMethodName("init");//设置初始化方法
      beanDefinition.setLazyInit(true);//设置懒加载

      声明式定义和编程式定义的Bean,最终都会被Spring解析为对应的BeanDefinition对象,并放入Spring容器中。

      BeanDefinitionReader

      接下来介绍几种在Spring源码中常见的BeanDefinition读取器(BeanDefinitionReader

      AnnotatedBeanDefinitionReader

      可以直接把某个类转换为BeanDefinition,并且会解析该类上的注解,比如:

      AnnotationConfigApplicationContextcontext=newAnnotationConfigApplicationContext(AppConfig.class);

      AnnotatedBeanDefinitionReaderannotatedBeanDefinitionReader=newAnnotatedBeanDefinitionReader(context);

      //将User.class解析为BeanDefinition
      annotatedBeanDefinitionReader.register(User.class);

      System.out.println(context.getBean("user"));/pre><p>它能解析的注解有:@Conditional,@Scope、@Lazy、@Primary、@DependsOn、@Role、@Description</p

      XmlBeanDefinitionReader

      可以解析<bean/>标签

      AnnotationConfigApplicationContextcontext=newAnnotationConfigApplicationContext(AppConfig.class);

      XmlBeanDefinitionReaderxmlBeanDefinitionReader=newXmlBeanDefinitionReader(context);
      inti=xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml");

      System.out.println(context.getBean("user"));

      ClassPathBeanDefinitionScanner

      ClassPathBeanDefinitionScanner是扫描器,它的作用和BeanDefinitionReader类似,可以进行扫描,扫描某个包路径,对扫描到的类进行解析,比如,扫描到的类上如果存在 code>@Component</code 注解,那么就会把这个类解析成为一个BeanDefinition

      AnnotationConfigApplicationContextcontext=newAnnotationConfigApplicationContext();
      context.refresh();

      ClassPathBeanDefinitionScannerscanner=newClassPathBeanDefinitionScanner(context);
      scanner.scan("cn.xx");

      System.out.println(context.getBean("user"));

      BeanFactory

      BeanFactory表示Bean工厂,所以很明显,BeanFactory会负责创建Bean,并且提供获取Bean的API。

      而ApplicationContext是BeanFactory的一种,在Spring源码中,是这么定义的:

      publicinterfaceApplicationContextextendsEnvironmentCapable,ListableBeanFactory,HierarchicalBeanFactory,
      MessageSource,ApplicationEventPublisher,ResourcePatternResolver{
      ...
      }

      首先,在Java中,接口是可以多继承的,我们发现ApplicationContext继承了ListableBeanFactoryHierarchicalBeanFactory,而 ListableBeanFactory 和HierarchicalBeanFactory 都继承至 BeanFactory,所以我们可以认为 ApplicationContext 继承了BeanFactory,相当于苹果继承水果,宝马继承汽车一样,ApplicationContext 也是 BeanFactory 的一种,拥有 BeanFactory 支持的所有功能,不过 ApplicationContext 比 BeanFactory 更加强大,ApplicationContext 还继承了其他接口,也就表示 ApplicationContext 还拥有其他功能,比如MessageSource 表示国际化,ApplicationEventPublisher 表示事件发布,EnvironmentCapable 表示获取环境变量等等,关于 ApplicationContext 后面再详细讨论。

      在Spring的源码中,当我们new一个ApplicationContext时,其底层会new一个BeanFactory,当使用ApplicationContext的某些方法时,比如getBean(),底层调用的就是BeanFactory的getBean()方法。

      在Spring源码中,BeanFactory接口存在一个非常重要的实现类是:DefaultListableBeanFactory,也是非常核心的。

      所以,我们可以直接使用DefaultListableBeanFactory,而不需要使用 ApplicationContext 的某个实现类,比如:

      DefaultListableBeanFactorybeanFactory=newDefaultListableBeanFactory();
      AbstractBeanDefinitionbeanDefinition=BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
      beanDefinition.setBeanClass(User.class);
      beanFactory.registerBeanDefinition("user",beanDefinition);
      System.out.println(beanFactory.getBean("user"));

      DefaultListableBeanFactory是非常强大的,支持很多功能,可以通过查看DefaultListableBeanFactory 的类继承结构图:

      Spring怎么创建Bean的生命周期

      • AliasRegistry:支持别名功能,一个名字可以对应多个别名

      • BeanDefinitionRegistry:可以注册、保存、移除、获取某个

      • BeanDefinitionBeanFactory:Bean工厂,可以根据某个bean的名字、或类型、或别名获取某个Bean对象

      • SingletonBeanRegistry:可以直接注册、获取某个单例Bean

      • SimpleAliasRegistry:它是一个类,实现了AliasRegistry接口中所定义的功能,支持别名功能

      • ListableBeanFactory:在BeanFactory的基础上,增加了其他功能,可以获取所有BeanDefinition的beanNames,可以根据某个类型获取对应的beanNames,可以根据某个类型获取{类型:对应的Bean}的映射关系

      • HierarchicalBeanFactory:在BeanFactory的基础上,添加了获取父BeanFactory的功能

      • DefaultSingletonBeanRegistry:它是一个类,实现了SingletonBeanRegistry接口,拥有了直接注册、获取某个单例Bean的功能

      • ConfigurableBeanFactory:在HierarchicalBeanFactory和SingletonBeanRegistry的基础上,添加了设置父BeanFactory、类加载器(表示可以指定某个类加载器进行类的加载)、设置Spring EL表达式解析器(表示该BeanFactory可以解析EL表达式)、设置类型转化服务(表示该BeanFactory可以进行类型转化)、可以添加BeanPostProcessor(表示该BeanFactory支持Bean的后置处理器),可以合并BeanDefinition,可以销毁某个Bean等等功能

      • FactoryBeanRegistrySupport:支持了FactoryBean的功能

      • AutowireCapableBeanFactory:是直接继承了BeanFactory,在BeanFactory的基础上,支持在创建Bean的过程中能对Bean进行自动装配

      • AbstractBeanFactory:实现了ConfigurableBeanFactory接口,继承了FactoryBeanRegistrySupport,这个BeanFactory的功能已经很全面了,但是不能自动装配和获取beanNames

      • ConfigurableListableBeanFactory:继承了ListableBeanFactory、AutowireCapableBeanFactory、ConfigurableBeanFactoryAbstract

      • AutowireCapableBeanFactory:继承了AbstractBeanFactory,实现了AutowireCapableBeanFactory,拥有了自动装配的功能

      • DefaultListableBeanFactory:继承了AbstractAutowireCapableBeanFactory,实现了ConfigurableListableBeanFactory接口和BeanDefinitionRegistry接口,所以DefaultListableBeanFactory的功能很强大

      ApplicationContext

      ApplicationContext 是个接口,实际上也是一个BeanFactory,不过比BeanFactory更加强大,比如:

      • HierarchicalBeanFactory:拥有获取父BeanFactory的功能

      • ListableBeanFactory:拥有获取beanNames的功能

      • ResourcePatternResolver:资源加载器,可以一次性获取多个资源(文件资源等等)

      • EnvironmentCapable:可以获取运行时环境(没有设置运行时环境的功能)

      • ApplicationEventPublisher:拥有广播事件的功能(没有添加事件监听器的功能)

      • MessageSource:拥有国际化功能

      ApplicationContext 有两个比较重要的实现类:

      • AnnotationConfigApplicationContext

      • ClassPathXmlApplicationContext

      AnnotationConfigApplicationContext

      Spring怎么创建Bean的生命周期

      ClassPathXmlApplicationContext

      Spring怎么创建Bean的生命周期

      它也是继承了AbstractApplicationContext,但是相对于AnnotationConfigApplicationContext而言,功能没有AnnotationConfigApplicationContext强大,比如不能注册BeanDefinition

      资源加载

      ApplicationContext还拥有资源加载的功能,比如,可以直接利用ApplicationContext获取某个文件的内容:

      AnnotationConfigApplicationContextcontext=newAnnotationConfigApplicationContext(AppConfig.class);

      Resourceresource=context.getResource("file:/Users/xiexu/Library/MobileDocuments/com~apple~CloudDocs/SSM/day01/src/main/java/cn/xx/domain/User.java");
      System.out.println(resource.contentLength());

      Resourceresource1=context.getResource("https://www.baidu.com&quot;);
      System.out.println(resource1.contentLength());
      System.out.println(resource1.getURL());

      Resourceresource2=context.getResource("classpath:spring.xml");
      System.out.println(resource2.contentLength());
      System.out.println(resource2.getURL());

       //可以一次性获取多个

      Resource[]resources=context.getResources("classpath:cn/xx/domain/*.class");
      for(Resourceresource3:resources){
      System.out.println(resource3.contentLength());
      System.out.println(resource3.getFilename());
      }

      事件发布

      先定义一个事件监听器:

       @Bean
      publicApplicationListenerapplicationListener(){
      returnnewApplicationListener(){
      @Override
      publicvoidonApplicationEvent(ApplicationEventevent){
      System.out.println("接收到了一个事件");
      }
      };
      }

      然后发布一个事件:

      AnnotationConfigApplicationContextcontext=newAnnotationConfigApplicationContext(AppConfig.class);

      context.publishEvent("kkk");

      类型转化

      在Spring源码中,有可能需要把String转成其他类型,所以在Spring源码中提供了一些技术来更方便的做对象的类型转化,关于类型转化的应用场景, 后续看源码的过程中会遇到很多。

      PropertyEditor

      这其实是JDK中提供的类型转化工具

      publicclassStringToUserPropertyEditorextendsPropertyEditorSupportimplementsPropertyEditor{

      @Override
      publicvoidsetAsText(Stringtext)throwsIllegalArgumentException{
      Useruser=newUser();
      user.setName(text);
      this.setValue(user);
      }

      }

      StringToUserPropertyEditorpropertyEditor=newStringToUserPropertyEditor();
      propertyEditor.setAsText("1");
      Uservalue=(User)propertyEditor.getValue();
      System.out.println(value);

      在Spring容器中注册 PropertyEditor:

       @Bean
      publicCustomEditorConfigurercustomEditorConfigurer(){
      CustomEditorConfigurercustomEditorConfigurer=newCustomEditorConfigurer();
      Map<Class<?>,Class<?extendsPropertyEditor>>propertyEditorMap=newHashMap<>();

      /*
      表示StringToUserPropertyEditor可以将String转化成User类型,
      在Spring源码中,如果发现当前对象是String,而需要的类型是User,
      就会使用该PropertyEditor来做类型转化
      */
      propertyEditorMap.put(User.class,StringToUserPropertyEditor.class);
      customEditorConfigurer.setCustomEditors(propertyEditorMap);
      returncustomEditorConfigurer;
      }

      假设现在有如下 Bean:

      @Component
      publicclassTest{

      @Value("xiaoming")
      privateUseruser;

      publicvoidtest(){
      System.out.println(user);
      System.out.println(user.getName());
      }
      }

      Spring怎么创建Bean的生命周期

      ConversionService

      Spring中提供的类型转化服务,它比PropertyEditor更强大

      publicclassStringToUserConverterimplementsConditionalGenericConverter{

      @Override
      publicbooleanmatches(TypeDescriptorsourceType,TypeDescriptortargetType){
      returnsourceType.getType().equals(String.class)&&targetType.getType().equals(User.class);
      }

      @Override
      publicSet<ConvertiblePair>getConvertibleTypes(){
      returnCollections.singleton(newConvertiblePair(String.class,User.class));
      }

      @Override
      publicObjectconvert(Objectsource,TypeDescriptorsourceType,TypeDescriptortargetType){
      Useruser=newUser();
      user.setName((String)source);
      returnuser;
      }

      }

      DefaultConversionServiceconversionService=newDefaultConversionService();
      conversionService.addConverter(newStringToUserConverter());
      Uservalue=conversionService.convert("1",User.class);
      System.out.println(value);

      在Spring中注册ConversionService:

       @Bean
      publicConversionServiceFactoryBeanconversionService(){
      ConversionServiceFactoryBeanconversionServiceFactoryBean=newConversionServiceFactoryBean();
      conversionServiceFactoryBean.setConverters(Collections.singleton(newStringToUserConverter()));

      returnconversionServiceFactoryBean;
      }

      TypeConverter

      整合了PropertyEditor和ConversionService的功能,是Spring内部用的:

      SimpleTypeConvertertypeConverter=newSimpleTypeConverter();
      typeConverter.registerCustomEditor(User.class,newStringToUserPropertyEditor());
      Uservalue=typeConverter.convertIfNecessary("xxx",User.class);
      System.out.println(value);
      System.out.println(value.getName());
      SimpleTypeConvertertypeConverter=newSimpleTypeConverter();
      DefaultConversionServiceconversionService=newDefaultConversionService();
      conversionService.addConverter(newStringToUserConverter());
      typeConverter.setConversionService(conversionService);
      Uservalue=typeConverter.convertIfNecessary("xxx",User.class);
      System.out.println(value);
      System.out.println(value.getName());/pre><h4>OrderComparator</h4><p>OrderComparator是Spring所提供的一种比较器,可以根据<code>@Order</code注解或实现Ordered接口来进行值的比较,从而可以进行排序。

      publicclassAimplementsOrdered{

      @Override
      publicintgetOrder(){
      return3;
      }

      @Override
      publicStringtoString(){
      returnthis.getClass().getSimpleName();
      }
      }

      publicclassBimplementsOrdered{

      @Override
      publicintgetOrder(){
      return2;
      }

      @Override
      publicStringtoString(){
      returnthis.getClass().getSimpleName();
      }
      }

      publicclassMain{

      publicstaticvoidmain(String[]args){
      Aa=newA();//order=3
      Bb=newB();//order=2

      OrderComparatorcomparator=newOrderComparator();
      System.out.println(comparator.compare(a,b));//1

      Listlist=newArrayList<>();
      list.add(a);
      list.add(b);

      //按order值升序排序
      list.sort(comparator);

      System.out.println(list);//B,A
      }

      }/pre><p>另外,Spring中还提供了一个OrderComparator的子类:<strong>AnnotationAwareOrderComparator</strong>,它支持用<code>@Order</code来指定order值。

      比如:

      @Order(3)
      publicclassA{

      @Override
      publicStringtoString(){
      returnthis.getClass().getSimpleName();
      }

      }

      @Order(2)
      publicclassB{

      @Override
      publicStringtoString(){
      returnthis.getClass().getSimpleName();
      }

      }

      publicclassMain{

      publicstaticvoidmain(String[]args){
      Aa=newA();//order=3
      Bb=newB();//order=2

      AnnotationAwareOrderComparatorcomparator=newAnnotationAwareOrderComparator();
      System.out.println(comparator.compare(a,b));//1

      Listlist=newArrayList<>();
      list.add(a);
      list.add(b);

      //按order值升序排序
      list.sort(comparator);

      System.out.println(list);//B,A
      }

      }

      BeanPostProcessor

      BeanPostProcess 表示Bean的后置处理器,我们可以定义一个或多个BeanPostProcessor

      @Component
      publicclassXiexuBeanPostProcessorimplementsBeanPostProcessor{

      @Override
      publicObjectpostProcessBeforeInitialization(Objectbean,StringbeanName)throwsBeansException{
      if("user".equals(beanName)){
      System.out.println("初始化前");
      }
      returnbean;
      }

      @Override
      publicObjectpostProcessAfterInitialization(Objectbean,StringbeanName)throwsBeansException{
      if("user".equals(beanName)){
      System.out.println("初始化后");
      }
      returnbean;
      }

      }

      一个BeanPostProcessor可以在任意一个Bean初始化前以及初始化后去额外的做一些用户自定义的逻辑,当然,我们可以通过判断beanName来进行针对性处理(针对某个Bean,或某部分Bean)。

      我们可以通过定义BeanPostProcessor来干涉Spring创建Bean的过程。

      BeanFactoryPostProcessor

      BeanFactoryPostProcessor表示Bean工厂的后置处理器,其实和BeanPostProcessor类似,BeanPostProcessor是干涉Bean的创建过程,BeanFactoryPostProcessor是干涉BeanFactory的创建过程。

      比如,我们可以这样定义一个BeanFactoryPostProcessor:

      @Component
      publicclassXiexuBeanFactoryPostProcessorimplementsBeanFactoryPostProcessor{

      @Override
      publicvoidpostProcessBeanFactory(ConfigurableListableBeanFactorybeanFactory)throwsBeansException{
      System.out.println("加工beanFactory");
      }
      }

      可以在postProcessBeanFactory()方法中对BeanFactory进行加工。

      FactoryBean

      上面提到,我们可以通过BeanPostPorcessor来干涉Spring创建Bean的过程,但是如果我们想一个Bean完完全全由我们自己来创造,也是可以的,比如通过FactoryBean:

      @Component
      publicclassXiexuFactoryBeanimplementsFactoryBean{

      @Override
      publicObjectgetObject()throwsException{
      Useruser=newUser();

      returnuser;
      }

      @Override
      publicClass<?>getObjectType(){
      returnUser.class;
      }
      }

      通过上面这段代码,我们自己创造了一个User对象,并且它将成为Bean。但是通过这种方式创造出来的User的Bean,只会经过初始化后,其他Spring的生命周期步骤是不会经过的,比如依赖注入。

      注意:单例池里面还是原来的xiexuFactoryBean,而通过getObject()方法返回的userBean是存放在factoryBeanObjectCache里面(缓存)。

      Spring怎么创建Bean的生命周期

      AnnotationConfigApplicationContextcontext=newAnnotationConfigApplicationContext(AppConfig.class);
      //如果beanName加上&,表示获取的是单例池里面的XiexuFactoryBean
      Objectbean1=context.getBean("&xiexuFactoryBean");
      System.out.println(bean1);//cn.xx.domain.XiexuFactoryBean@2de8284b

      //如果beanName没有加上&,表示获取的是factoryBeanObjectCache缓存里面的userBean
      Objectbean2=context.getBean("xiexuFactoryBean");
      System.out.println(bean2);//cn.xx.domain.User@396e2f39/pre><p>有同学可能会想到,通过@Bean也可以自己生成一个对象作为Bean,那么和FactoryBean的区别是什么呢?其实在很多场景下他俩是可以替换的,但是站在原理层面来说,区别也很明显,@Bean定义的Bean是会经过完整的Bean生命周期的。</p

      ExcludeFilter 和 IncludeFilter

      这两个Filter是Spring扫描过程中用来过滤的。ExcludeFilter 表示排除过滤器IncludeFilter 表示strong>包含过滤器</strong>。</p><p>比如以下配置,表示扫描<code>cn.xx</code>这个包下面的所有类,但是排除<code>UserService</code>类,</p><p>就算<code>UserService</code>类上面有<code>@Component</code注解也不会成为Bean。

      @ComponentScan(value="cn.xx",
      excludeFilters={@ComponentScan.Filter(
      type=FilterType.ASSIGNABLE_TYPE,
      classes=UserService.class)})
      publicclassAppConfig{
      }/pre><p>再比如以下配置,就算<code>UserService</code>类上没有<code>@Component</code注解,它也会被扫描成为一个Bean。

      @ComponentScan(value="cn.xx",
      includeFilters={@ComponentScan.Filter(
      type=FilterType.ASSIGNABLE_TYPE,
      classes=UserService.class)})
      publicclassAppConfig{
      }

      FilterType分为:

        li><p><strong>ANNOTATION</strong>:表示是否包含某个注解</p></li><li><p><strong>ASSIGNABLE_TYPE</strong>:表示是否是某个类</p></li><li><p><strong>ASPECTJ</strong>:表示是否符合某个Aspectj表达式</p></li><li><p><strong>REGEX</strong>:表示是否符合某个正则表达式</p></li><li><p><strong>CUSTOM</strong>:自定义</p></li></ul><p>在Spring的扫描逻辑中,默认会添加一个<code>AnnotationTypeFilter</code>给<code>includeFilters</code>,表示默认情况下在Spring扫描过程中会认为类上有<code>@Component</code注解的就是Bean。

        MetadataReader、ClassMetadata、AnnotationMetadata

        在Spring中需要去解析类的信息,比如类名、类中的方法、类上的注解,这些都可以称之为类的元数据,所以Spring中对类的元数据做了抽象,并提供了一些工具类。

        MetadataReader表示类的元数据读取器,默认实现类为SimpleMetadataReader。比如:

        publicclassTest{

        publicstaticvoidmain(String[]args)throwsIOException{
        SimpleMetadataReaderFactorysimpleMetadataReaderFactory=newSimpleMetadataReaderFactory();

        //构造一个MetadataReader
        MetadataReadermetadataReader=simpleMetadataReaderFactory.getMetadataReader("cn.xx.service.impl.UserServiceImpl");

        //得到一个ClassMetadata,并获取了类名
        ClassMetadataclassMetadata=metadataReader.getClassMetadata();

        System.out.println(classMetadata.getClassName());

        //获取一个AnnotationMetadata,并获取类上的注解信息
        AnnotationMetadataannotationMetadata=metadataReader.getAnnotationMetadata();
        for(StringannotationType:annotationMetadata.getAnnotationTypes()){
        System.out.println(annotationType);
        }
        }
        }

        5.Spring之Bean生命周期源码解析

        Spring 扫描底层流程(doScan方法)

        生成BeanDefinition

          li><p>首先通过ResourcePatternResolver获得指定包路径下的所有<code>.class</code>文件(Spring源码中将此文件包装成了<code>Resource</code>对象)</p></li><li><p>遍历每个Resource对象利用<code>MetadataReaderFactory</code>解析Resource对象得到MetadataReader(在Spring源码中MetadataReaderFactory具体的实现类为CachingMetadataReaderFactory,MetadataReader的具体实现类为SimpleMetadataReader)</p></li><li><p>利用MetadataReader进行<code>excludeFilters</code>和<code>includeFilters</code>,以及条件注解<code>@Conditional</code的筛选(某个类上是否存在code>@Conditional</code注解,如果存在则调用注解中所指定的类的code>match</code>方法进行匹配,匹配成功则通过筛选,匹配失败则pass掉)</p></li><li><p>筛选通过后,基于metadataReader生成<code>ScannedGenericBeanDefinition</code>再基于metadataReader判断对应的类是不是接口或抽象类</p></li><li><p>如果筛选通过,就表示扫描到了一个Bean,将ScannedGenericBeanDefinition加入结果集</p></li></ul><p><strong>注意:</strong></p><p>上面说的是通过扫描得到BeanDefinition对象,我们还可以通过直接定义BeanDefinition,或解析spring.xml文件的<code>&lt;bean&gt;</code>,或者@Bean注解得到BeanDefinition对象。</p

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

          • 获取类的名字

          • 获取父类的名字

          • 获取所实现的所有接口名

          • 获取所有内部类的名字

          • 判断是不是抽象类

          • 判断是不是接口

          • 判断是不是一个注解

          • 获取拥有某个注解的方法集合

          • 获取类上添加的所有注解信息

          • 获取类上添加的所有注解类型集合

          注意:

          CachingMetadataReaderFactory解析某个.class文件得到MetadataReader对象是利用 ASM 技术,并没有加载这个类到JVM中。并且最终得到的ScannedGenericBeanDefinition对象,它的 beanClass 属性存储的是当前类的名字,而不是class对象。(beanClass属性的类型是Object,它即可以存储类的名字,也可以存储类对象)

          合并BeanDefinition

          通过扫描得到所有的BeanDefinition之后,就可以根据BeanDefinition创建Bean对象了。在Spring中支持父子BeanDefinition,和Java子父类类似。

          父子BeanDefinition实际上用得比较少,例如:这么定义的情况下,child是单例Bean。

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

          但如果是下面这样,child就是原型Bean了。

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

          因为child的父BeanDefinition是parent,所以会继承parent上所定义的scope属性。

          所以在根据child来生成Bean对象之前,需要进行BeanDefinition的合并,才能得到完整的child的BeanDefinition。

          加载类

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

          Spring怎么创建Bean的生命周期

          Spring怎么创建Bean的生命周期

          publicbooleanhasBeanClass(){
          //判断当前BeanDefinition的beanClass属性,是不是Class类型
          return(this.beanClassinstanceofClass);
          }

          如果beanClass属性的类型是Class,那么就直接返回;如果不是,则会根据类名进行加载(doResolveBeanClass方法所做的事情)

          Spring怎么创建Bean的生命周期

           @Override
          @Nullable
          publicClassLoadergetBeanClassLoader(){
          returnthis.beanClassLoader;
          }

          @NullableprivateClassLoaderbeanClassLoader=ClassUtils.getDefaultClassLoader();</pre><p>先利用BeanFactory所设置的类加载器来加载类,如果没有设置,则默认使用<code>ClassUtils.getDefaultClassLoader()</code>所返回的类加载器来进行加载。</p><pre>/***获取默认的类加载器*/@NullablepublicstaticClassLoadergetDefaultClassLoader(){ClassLoadercl=null;/***优先获取线程中的类加载器*一开始,tomcat会将自定义的类加载器设置到线程上下文中,*然后当你走到这一步的时候,就可以获取到线程中的tomcat自定义类加载器*/try{cl=Thread.currentThread().getContextClassLoader();}catch(Throwableex){}//如果线程上下文中的类加载器为空,那就获取ClassUtils类所对应的类加载器if(cl==null){cl=ClassUtils.class.getClassLoader();if(cl==null){//如果类加载器等于null,就说明是引导类加载器//ClassUtils类是被Bootstrap类加载器加载的,则获取系统类加载器try{cl=ClassLoader.getSystemClassLoader();}catch(Throwableex){}}}//返回类加载器returncl;}</pre><blockquote><p><code>ClassUtils.getDefaultClassLoader()</code></p></blockquote><p>优先返回当前线程中的类加载器如果当前线程中的类加载器为空,则返回<code>ClassUtils</code>类的类加载器如果ClassUtils类的类加载器为空,那么表示是Bootstrap类加载器加载的ClassUtils类,那么则返回系统类加载器 4.实例化前</p><p>当前BeanDefinition对应的类加载成功后,就可以实例化对象了,但是&amp;hellip;</p><p>在实例化对象之前,Spring提供了一个扩展点,允许用户来控制是否在某些Bean实例化之前做一些启动动作。</p><p><img src="https://qixn-bj.oss-cn-beijing.aliyuncs.com/seosjz/uploadfile/all/png/onldxch1wcw.png" alt="Spring怎么创建Bean的生命周期"></p><p><img src="https://qixn-bj.oss-cn-beijing.aliyuncs.com/seosjz/uploadfile/all/png/2smu2zsscji.png" alt="Spring怎么创建Bean的生命周期"></p><p><img src="https://qixn-bj.oss-cn-beijing.aliyuncs.com/seosjz/uploadfile/all/png/quglg1dyywp.png" alt="Spring怎么创建Bean的生命周期"></p><p>这个扩展点叫<strong>InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation( )</strong>。比如:</p><pre>@ComponentpublicclassZhouyuBeanPostProcessorimplementsInstantiationAwareBeanPostProcessor{@OverridepublicObjectpostProcessBeforeInstantiation(Class&lt;?&gt;beanClass,StringbeanName)throwsBeansException{if(&quot;userService&quot;.equals(beanName)){System.out.println(&quot;实例化前&quot;);}returnnull;}}</pre><p>以上代码会导致,在<code>userService</code>这个Bean实例化前,会进行打印。</p><p>注意:<code>postProcessBeforeInstantiation()</code>是有返回值的,如果这么实现:</p><pre>@ComponentpublicclassZhouyuBeanPostProcessorimplementsInstantiationAwareBeanPostProcessor{@OverridepublicObjectpostProcessBeforeInstantiation(Class&lt;?&gt;beanClass,StringbeanName)throwsBeansException{if(&quot;userService&quot;.equals(beanName)){System.out.println(&quot;实例化前&quot;);returnnewUserService();}returnnull;}}</pre><p>userService这个Bean在实例化前会直接返回一个由我们所定义的UserService对象。如果是这样,表示不需要Spring来实例化了,并且后续的Spring依赖注入也不会进行了,会跳过一些步骤,直接执行初始化后这一步。</p><p>5.实例化</p><p>在这个步骤中就会根据BeanDefinition去创建一个对象了。</p><p>6.BeanDefinition的后置处理</p><p><img src="https://qixn-bj.oss-cn-beijing.aliyuncs.com/seosjz/uploadfile/all/png/wyxsipwo2vo.png" alt="Spring怎么创建Bean的生命周期"></p><p>Bean对象实例化之后,接下来就应该给对象的属性赋值了。在真正给属性赋值之前,Spring又提供了一个扩展点<strong>MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition( )</strong>,可以对此时的BeanDefinition进行加工,比如:</p><pre>@ComponentpublicclassZhouyuMergedBeanDefinitionPostProcessorimplementsMergedBeanDefinitionPostProcessor{@OverridepublicvoidpostProcessMergedBeanDefinition(RootBeanDefinitionbeanDefinition,Class&lt;?&gt;beanType,StringbeanName){if(&quot;userService&quot;.equals(beanName)){beanDefinition.getPropertyValues().add(&quot;orderService&quot;,newOrderService());//注入属性}}}</pre><p>在Spring源码中,AutowiredAnnotationBeanPostProcessor 就是一个MergedBeanDefinitionPostProcessor,它的<code>postProcessMergedBeanDefinition()</code>方法中会去查找注入点,并缓存在AutowiredAnnotationBeanPostProcessor对象的一个Map中(injectionMetadataCache)。</p><p>7.实例化后</p><p><img src="https://qixn-bj.oss-cn-beijing.aliyuncs.com/seosjz/uploadfile/all/png/iflzbyk0mus.png" alt="Spring怎么创建Bean的生命周期"></p><p><img src="https://qixn-bj.oss-cn-beijing.aliyuncs.com/seosjz/uploadfile/all/png/ozuuuhhzum4.png" alt="Spring怎么创建Bean的生命周期"></p><p>在处理完BeanDefinition后,Spring又设计了一个扩展点:<strong>InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation( )</strong>,比如:</p><pre>@ComponentpublicclassZhouyuInstantiationAwareBeanPostProcessorimplementsInstantiationAwareBeanPostProcessor{@OverridepublicbooleanpostProcessAfterInstantiation(Objectbean,StringbeanName)throwsBeansException{if(&quot;userService&quot;.equals(beanName)){UserServiceuserService=(UserService)bean;userService.test();}returntrue;}}</pre><p>上述代码就是对userService所实例化出来的对象进行处理。</p><p>注意:这个扩展点在Spring源码中基本没有怎么使用。</p><p>8.自动注入 9.处理属性</p><p><img src="https://qixn-bj.oss-cn-beijing.aliyuncs.com/seosjz/uploadfile/all/png/cqri4jkwfnl.png" alt="Spring怎么创建Bean的生命周期"></p><pre>/***这里会调用AutowiredAnnotationBeanPostProcessor的postProcessProperties()方法,会直接给对象中的属性赋值*AutowiredAnnotationBeanPostProcessor内部并不会处理pvs,直接返回了*并不会处理pvs指的是:*如果当前bean的某些属性已经通过postProcessMergedBeanDefinition方法注入了,那么该属性上面的@Autowired注解应该是无效的,*因为程序员已经将自定义的值设置到属性里面去了*/</pre><p>这个步骤中,就会处理<code>@Autowired</code>、<code>@Resource</code>、<code>@Value</code>等注解,也是通过**InstantiationAwareBeanPostProcessor.postProcessProperties( )**扩展点来实现的。</p><blockquote><p>比如:我们甚至可以实现一个自己的自动注入功能</p></blockquote><pre>@ComponentpublicclassZhouyuInstantiationAwareBeanPostProcessorimplementsInstantiationAwareBeanPostProcessor{@OverridepublicPropertyValuespostProcessProperties(PropertyValuespvs,Objectbean,StringbeanName)throwsBeansException{if(&quot;userService&quot;.equals(beanName)){for(Fieldfield:bean.getClass().getFields()){if(field.isAnnotationPresent(ZhouyuInject.class)){field.setAccessible(true);try{field.set(bean,&quot;123&quot;);}catch(IllegalAccessExceptione){e.printStackTrace();}}}}returnpvs;}}</pre><p>10.执行Aware</p><p><img src="https://qixn-bj.oss-cn-beijing.aliyuncs.com/seosjz/uploadfile/all/png/n1euj3puqcy.png" alt="Spring怎么创建Bean的生命周期"></p><p><img src="https://qixn-bj.oss-cn-beijing.aliyuncs.com/seosjz/uploadfile/all/png/rmlvsukwtlg.png" alt="Spring怎么创建Bean的生命周期"></p><blockquote><p>完成了属性赋值之后,Spring会执行一些回调,包括:</p></blockquote><p><code>BeanNameAware</code>:回传beanName给bean对象<code>BeanClassLoaderAware</code>:回传classLoader给bean对象<code>BeanFactoryAware</code>:回传beanFactory给对象 11.初始化前</p><p><img src="https://qixn-bj.oss-cn-beijing.aliyuncs.com/seosjz/uploadfile/all/png/rfyj0kl2uph.png" alt="Spring怎么创建Bean的生命周期"></p><p><img src="https://qixn-bj.oss-cn-beijing.aliyuncs.com/seosjz/uploadfile/all/png/ffzg0ce1g3p.png" alt="Spring怎么创建Bean的生命周期"></p><p>初始化前,也是Spring提供的一个扩展点:<strong>BeanPostProcessor.postProcessBeforeInitialization( )</strong>,比如:</p><pre>@ComponentpublicclassZhouyuBeanPostProcessorimplementsBeanPostProcessor{@OverridepublicObjectpostProcessBeforeInitialization(Objectbean,StringbeanName)throwsBeansException{if(&quot;userService&quot;.equals(beanName)){System.out.println(&quot;初始化前&quot;);}returnbean;}}</pre><p>利用初始化前,可以对已经进行了依赖注入的Bean进行处理。</p><p>在Spring源码中:</p><p>InitDestroyAnnotationBeanPostProcessor 会在初始化前这个步骤中执行<code>@PostConstruct</code>的方法,ApplicationContextAwareProcessor 会在初始化前这个步骤中进行其他Aware的回调: EnvironmentAware:回传环境变量EmbeddedValueResolverAware:回传占位符解析器ResourceLoaderAware:回传资源加载器ApplicationEventPublisherAware:回传事件发布器MessageSourceAware:回传国际化资源ApplicationStartupAware:回传应用其他监听对象,可忽略ApplicationContextAware:回传Spring容器ApplicationContext 12.初始化</p><p><img src="https://qixn-bj.oss-cn-beijing.aliyuncs.com/seosjz/uploadfile/all/png/e0xjwrml1qq.png" alt="Spring怎么创建Bean的生命周期"></p><p><img src="https://qixn-bj.oss-cn-beijing.aliyuncs.com/seosjz/uploadfile/all/png/z0m4azn2gdj.png" alt="Spring怎么创建Bean的生命周期"></p><p>查看当前Bean对象是否实现了InitializingBean接口,如果实现了就调用其<code>afterPropertiesSet()</code>方法执行BeanDefinition中指定的初始化方法 13.初始化后</p><p><img src="https://qixn-bj.oss-cn-beijing.aliyuncs.com/seosjz/uploadfile/all/png/bomyjrs0iae.png" alt="Spring怎么创建Bean的生命周期"></p><p><img src="https://qixn-bj.oss-cn-beijing.aliyuncs.com/seosjz/uploadfile/all/png/4xy22tjlvgy.png" alt="Spring怎么创建Bean的生命周期"></p><p>这是Bean创建生命周期中的最后一个步骤,也是Spring提供的一个扩展点:<strong>BeanPostProcessor.postProcessAfterInitialization( )</strong>,比如:</p><pre>@ComponentpublicclassZhouyuBeanPostProcessorimplementsBeanPostProcessor{@OverridepublicObjectpostProcessAfterInitialization(Objectbean,StringbeanName)throwsBeansException{if(&quot;userService&quot;.equals(beanName)){System.out.println(&quot;初始化后&quot;);}returnbean;}}</pre><p>可以在这个步骤中,对Bean进行最终处理,Spring中的<strong>AOP就是基于初始化后实现</strong>的,<strong>初始化后返回的对象才是最终的Bean对象</strong>。</p><p>14.总结BeanPostProcessor</p><p>实例化前:</p><p><code>InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()</code></p><p>实例化</p><p><code>MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()</code></p><p>实例化后:</p><p><code>InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()</code></p><p>自动注入</p><p><code>InstantiationAwareBeanPostProcessor.postProcessProperties()</code></p><p>Aware对象</p><p>初始化前:</p><p><code>BeanPostProcessor.postProcessBeforeInitialization()</code></p><p>初始化</p><p>初始化后:</p><p><code>BeanPostProcessor.postProcessAfterInitialization()</code></p><p><img src="https://qixn-bj.oss-cn-beijing.aliyuncs.com/seosjz/uploadfile/all/png/f4vamzya4rs.png" alt="Spring怎么创建Bean的生命周期"></p>
          本文:Spring怎么创建Bean的生命周期的详细内容,希望对您有所帮助,信息来源于网络。

上一篇:常见的Struts2面试题及答案有哪些下一篇:

16 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18