• spring Bean


    1. Bean的装载与管理

    Spring框架中,一旦把一个Bean纳入到Spring IoC容器之中,这个Bean的生命周期就会交由容器进行管理,一般担当管理者角色的是BeanFactory或ApplicationContex。

    将Bean元数据收集装载

    BeanDefinition:用于管理各种对象以及它们之间相互依赖关系的核心数据结构。

    Resource:用来封装IO操作的类。

     收集过程:通过refresh方法启动,包括BeanDefinition和Resource的定位、载入、注册三个基本过程:

    
     -- 定位:即寻找数据的过程,指对BeanDefinition的资源定位,由ResourceLoader通过统一的Resource接口完成。
     -- 载入:把用户定义好的Bean表示成IOC容器的内部数据结构,即BeanDefinition(POJO对象在IOC容器中的抽象)
     -- 注册:将BeanDefinition注入到HashMap中,IOC容器就是通过这个HahMap来管理数据。

    BeanFactory接口

    Spring 的容器最基本的接口就是:BeanFactory。BeanFactory 负责配置、创建及管理bean。

    调用者只需使用getBean 方法即可获得指定bean的引用,无须关心bean 的实例化过程。即bean 实例的创建过程完全透明。

    通过BeanFactory获取Bean

    在UserService中注入tool字段,通过BeanFactory来实现获取

    UserService实现BeanFactoryAware接口的setBeanFactory方法,Spring会调用setBeanFactory方法将BeanFactory注入到UserService的factory字段(需要注意UserService需要被实例化,可以通过xml来配置bean,也可以通过@component类的注解来将Bean装载到容器实例化),然后就可以通过setBeanFactory获取Bean。

    ApplicationContext接口

    获取Bean推荐使用ApplicationContext,因为其是BeanFactory 的子接口,提供了更多面向应用的功能。

    通过ApplicationContext获取Bean:

    和BeanFactory一样,SpringConfigTool类也需要实例化,ApplicationContext才能被注入到context字段上,可以通过XML或者@component类型的注解,将Bean注入。

    BeanFactory与ApplicationContext区别:

    1. BeanFacotry延迟加载,即只有在使用到某个Bean时(调用getBean()),才对该Bean
      进行加载实例化,如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次
      使用调用getBean方法才会抛出异常;而ApplicationContext则在初始化自身是检验,
      这样有利于检查所依赖属性是否注入;所以通常情况下我们选择使用
      ApplicationContext。ApplicationContext则会在上下文启动后预载入所有的单
      实例Bean。通过预载入单实例bean ,确保当你需要的时候,你就不用等待,因为它们
      已经创建好了。
    2. 一旦单例被实例化就会被放入缓存Bean池,下次获取直接返回,而多例则每一次都创建
      一个新对象返回,并将控制权移交给用户,由用户管理Bean的生命周期,使用完后需要
      显示设置为null,帮助回收。BeanFactory只能管理单例Bean,而
      ApplicationContext也可以管理多例Bean。
    3. BeanFactory和ApplicationContext都支持BeanPostProcessor、
      BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动
      注册,而ApplicationContext则是自动注册。(Applicationcontext比
      beanFactory 加入了一些更好使用的功能。而且 BeanFactory的许多功能需要通过
      编程实现而 Applicationcontext 可以通过配置实现。比如后处理 bean ,
      Applicationcontext 直接配置在配置文件即可而 BeanFactory这要在代码中显示
      的写出来才可以被容器识别)。
    4. BeanFactory主要是面对与 Spring 框架的基础设施,面对 spring 自己。而
      Applicationcontext主要面对与 Spring 使用的开发者。基本都会使用
      Applicationcontext并非 BeanFactory。

    2. Bean 的生命周期

    BeanFactory实例化Bean属性相关实例化顺序

    1、调用Bean的默认构造方法,或者在指定的构造方法,生成bean实例(暂称为instance1);

    3、如果Bean的配置文件中注入了Bean属性值,则在instance1基础上进行属性注入形成instance2,这种注入是覆盖性的。

    2、如果Bean实现了InitializingBean接口,则调用afterPropertiesSet()方法,来改变或操作instance2,得到instance3;

    4、如果Bean的配置文件中指定了init-ethod="init"属性,则会调用指定的初始化方法,则在instance3的基础上调用初始化方法init(),将对象最终初始化为instance4;初始化的名字任意。

    Bean的具体加载与初始化

    1. 实例化一个Bean(由BeanFactory读取Bean定义文件,并生成各个实例)--也就是我们常说的new;

    2. 按照Spring上下文对实例化的Bean的属性值进行设置--也就是IOC注入;

    3. 如果这个Bean已经实现了BeanNameAware接口,会调用它实现的setBeanName(String)方法,此处传递的就是Spring配置文件中Bean的id值

    4. 如果这个Bean已经实现了BeanFactoryAware接口,会调用它实现的setBeanFactory(setBeanFactory(BeanFactory)传递的是Spring工厂自身(可以用这个方式来获取其它Bean,只需在Spring配置文件中配置一个普通的Bean就可以);

    5. 如果这个Bean已经实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文(同样这个方式也可以实现步骤4的内容,但比4更好,因为ApplicationContext是BeanFactory的子接口,有更多的实现方法);

    6. 如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessBeforeInitialization(Object obj, String s)方法

    初始化之前构造注入依赖之后执行

    1. 如果Bean类实现了org.springframework.beans.factory.InitializingBean接口,则执行其afterPropertiesSet()方法。

    一般是用来在实例构造完成后,实例的应该注入的依赖属性已经完成注入,需要对不需要注入的实例属性进行自定义初始化配置;当然也可指定一个init-method方法完成初始化,两者的作用一样,都是完成用户自定义初始化。对于单例,如果bean实现了InitializingBean接口则afterPropertiesSet方法只会被调用一次;否则每次创建bean时afterPropertiesSet方法都会被重新调用。

    1. 如果Bean在Spring配置文件中配置了init-method属性会自动调用其配置的初始化方法。

    或者使用@PostConstruct后构造注解来将任意方法名称的方法标明为一个init-method方法

    1. 如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessAfterInitialization(Object obj, String s)方法;

    注:以上工作完成以后就可以应用这个Bean了,如果这个Bean是一个Singleton的,则将这准备就绪的Bean放入Spring缓存池中,已被下次使用,所以一般情况下我们调用同一个id的Bean会是在内容地址相同的实例,当然在Spring配置文件中也可以配置非Singleton,此时不会将Bean放入缓存池中,而是直接将控制权交给Bean的使用者。

    1. 当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用那个其实现的destroy()方法;

    2. 最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。

    可以使用@PreDestroy前销毁注解,标明一个方法为destroy-method

    说明: 如果Bean是由BeanFactory管理,则没有第五步,同样如果由ApplicationContext管理,则没有第四步。

    摘自Spring BeanFactoy官方文档:

    Bean factory implementations should support the standard bean lifecycle interfaces as far as possible. The full set of initialization methods and their standard order is:

    -- BeanNameAware's setBeanName

    -- BeanClassLoaderAware's setBeanClassLoader

    -- BeanFactoryAware's setBeanFactory

    -- EnvironmentAware's setEnvironment

    -- EmbeddedValueResolverAware's setEmbeddedValueResolver

    -- ResourceLoaderAware's setResourceLoader (only applicable when running in an application context)

    -- ApplicationEventPublisherAware's setApplicationEventPublisher (only applicable when running in an application context)

    -- MessageSourceAware's setMessageSource (only applicable when running in an application context)

    -- ApplicationContextAware's setApplicationContext (only applicable when running in an application context)

    -- ServletContextAware's setServletContext (only applicable when running in a web application context)

    -- postProcessBeforeInitialization methods of BeanPostProcessors

    -- InitializingBean's afterPropertiesSet

    -- a custom init-method definition

    -- postProcessAfterInitialization methods of BeanPostProcessors

    On shutdown of a bean factory, the following lifecycle methods apply:

    -- postProcessBeforeDestruction methods of DestructionAwareBeanPostProcessors

    -- DisposableBean's destroy

    -- a custom destroy-method definition

     

    3. 装配注解

    • @Autowired,该注解的作用是:可以对成员变量、方法和构造函数进行注解,来完成自动装配的工作,通俗来说就是会根据类型从容器中自动查到到一个Bean给bookDAO字段。@Autowired是根据类型进行自动装配的,如果需要按名称进行装配,则需要配合@Qualifier。另外可以使用其它注解,
    • @ Resource :等同于@Qualifier
    • @Inject:等同于@ Autowired。

     @Resource

    默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入;

    @Autowired

    默认是按照类型装配注入的,如果想按照名称来转配注入,则需要结合@Qualifier一起使用;

    @Resource

    注解是又J2EE提供,而@Autowired是由spring提供,故减少系统对spring的依赖建议使用@Resource的方式;如果Maven项目是1.5的JRE则需换成更高版本的。

    @Resource和@Autowired都可以书写注解在字段或者该字段的setter方法之上

    @Autowired

    可以对成员变量、方法以及构造函数进行注释,而 @Qualifier 的注解对象是成员变量、方法入参、构造函数入参。

    @Qualifier("XXX")

    中的 XX是 Bean 的名称,所以 @Autowired 和 @Qualifier 结合使用时,自动注入的策略就从 byType 转变成 byName 了。

    @Autowired 注释进行自动注入时

    Spring 容器中匹配的候选 Bean 数目必须有且仅有一个,通过属性required可以设置非必要。

    参考:https://www.jianshu.com/p/f4ef69419bb2?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

      https://www.jianshu.com/p/9062236edeea

  • 相关阅读:
    android 21 隐式意图启动系统预定义activity
    android 20 Intnet类重要的成员变量
    android 19 activity纵横屏切换的数据保存与恢复
    android 18 Bundle类
    android 17 activity生命周期
    Centos6.4建立本地yum源
    eclipse实现批量修改文件的编码方式
    [系统资源]/proc/meminfo和free输出解释
    监控WebLogic 8.x的解决方案(监控应用服务器系列文章)
    linux网络监控脚本
  • 原文地址:https://www.cnblogs.com/yelao/p/10843699.html
Copyright © 2020-2023  润新知