Spring IoC容器-BeanFactory

SpringIoC容器用来容纳我们开发的各种Bean,并且我们可以从中获取各种发布在Spring IoC容器中的Bean,并通过描述来获取它。

Spring Ioc容器的设计

Spring IoC容器的设计主要是基于BeanFactory和ApplicationContext两个接口,其中ApplicationContext是BeanFactory的子接口,BeanFactory是Spring IoC容器所定义的最底层的接口,ApplicationContext是其高级接口之一,并且对BeanFactory的功能做了增强,所以我们主要使用ApplicatinContext作为Spring IoC的容器。

IOC接口设计

BeanFactory类的体系结构

Spring为BeanFactory提供了很多的实现类,如图

  • BeanFactory:该接口位于类接口的顶层,它主要的方法就是getBean(String beanName),该方法送容器中返回特定名称的Bean,BeanFactory的功能通过其他接口得到不断扩展。
  • ListableBeanFactory:该接口定义了访问容器中Bean基本信息的若干方法,如查看Bean的个数,获取某一类型Bean的配置名,查看容器中是否包含某一个Bean等。
  • HierarchicalBeanFactory:父子级联IoC容器的接口,子容器可以通过接口方法访问父容器。
  • ConfigurableBeanFactory:这个接口增强了IoC容器的可定制性,它定义了设置类装载器,属性编辑器,容器初始化后置处理器等方法
  • AutowireCapableBeanFactory:定义了将容器中的Bean按某种规则(如按名字匹配,按类型匹配等)进行自动装配的方法
  • SingletonBeanRegistry:定义了允许在运行期向容器注册单个实例Bean的方法
  • BeanDefinitionRegistry:Spring配置文件中每一个节点元素在Spring里都通过一个BeanDefinition对象表示,它描述了Bean的配置信息。而接口BeanDefinitionRegistry接口提供了向容器手工注册BeanDefinition对象的方法。

BeanFactory的Bean的生命周期

具体过程

  1. 当调用者通过getBean(beanName)向容器中请求某一个Bean时,如果容器注册了org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor接口,则在实例化Bean之前,将调用接口postProcessBeforeInstantiation方法。具体可以查看AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd)方法
  2. 根据配置情况调用Bean构造函数或工厂方法实例化Bean。可以查看AbstractAutowireCapableBeanFactory.doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)方法
  3. 如果容器注册了InstantiationAwareBeanPostProcessor接口,那么在实例化Bean之后,调用该接口的postProcessAfterInstantiation方法,可在这里对已经实例化的对象进行一些处理
  4. 如果Bean配置了属性信息,那么容器在这一步着手将配置设置到Bean队形的属性中,不过在设置每个属性之前将先调用InstantiationAwareBeanPostProcessor接口的postProcessPropertyValues方法
  5. 调用Bean的属性设置方法设置属性值
  6. 如果Bean实现了org.springframework.beans.factory.BeanNameAware接口,则将调用setBeanName接口方法,将配置文件中该Bean对应的名称设置到Bean中
  7. 如果Bean实现了org.springframework.beans.factory.BeanFactoryAware接口,则将调用setBeanFactory接口方法,将BeanFactory容器实例设置到Bean中
  8. 如果BeanFactory装配了org.springframework.beans.factory.config.BeanPostProcessor后处理器,则调用BeanPostProcessor的Object postProcessBeforeInitialization(Object bean, String beanName) 接口方法对Bean进行加工操作,其中,入参bean是当前正处理的Bean,而beanName是当前Bean的配置名,返回的对象为加工处理后的Bean。用户可以使用该方法对某些Bean进行特殊的处理,甚至改变Bean的行为
  9. 如果Bean实现了InitializingBean接口,则将调用接口的afterPropertiesSet()方法
  10. 如果在bean中通过init-method属性定义了初始化方法,则将执行这个方法
  11. BeanPostProcessor后处理器定义了两个方法,postProcessBeforeInitialization()在第八步调用,Object postProcessAfterInitialization(Object bean, String beanName)这个方法在此时调用,容器再次获得对Bean加工处理的机会
  12. 如果在bean中指定Bean的作用范围为scope="prototype",则将Bean返回给调用者,调用者负责Bean后续的生命管理,Spring不再管理这个Bean的生命周期。如果将作用范围设置为scope="singleton",则将Bean放入Spring IoC容器的缓存池中,并将Bean引用返回给调用者,Spring继续对这些Bean进行后续的生命周期管理
  13. 对于scope="singleton"的Bean,当容器关闭时,将触发Spring对Bean后续生命周期的管理工作。如果Bean实现了DisposableBean接口,则将调用接口的destory()方法,可以再次编写释放资源、记录日志等操作
  14. 对于scope="singleton"的Bean,如果通过Bean的destroy-method属性执行了Bean的销毁方法,那么Spring将执行Bean的这个方法,完成Bean资源释放等操作

Bean声明周期实例

定义一个Bean类并实现BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean接口

public class Animal implements BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean {
    private String name;
    private int age;
    private BeanFactory beanFactory;
    private String beanName;

    public Animal() {
        System.out.println("调用Animal的构造方法");
    }

    public void setName(String name) {
        System.out.println("调用AnimalsetName设置属性");
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("调用BeanFactoryAware.setBeanFactory()");
        this.beanFactory = beanFactory;
    }

    @Override
    public void setBeanName(String beanName) {
        System.out.println("调用BeanNameAware.setBeanName()。");
        this.beanName = beanName;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("调用InitializingBean.afterPropertiesSet()。");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("调用DisposableBean.destory()。");
    }

    public void myInit() {
        System.out.println("调用myInit(),");

    }

    public void myDestory() {
        System.out.println("调用myDestroy()。");
    }

    @Override
    public String toString() {
        return "Animal{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", beanFactory=" + beanFactory +
                '}';
    }
}

定义一个MyInstantiationAwareBeanPostProcessor并继承InstantiationAwareBeanPostProcessorAdapter

public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {

        if ("animal".equals(beanName)) {
            System.out.println("MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation");
        }
        return super.postProcessBeforeInstantiation(beanClass, beanName);
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if ("animal".equals(beanName)) {
            System.out.println("InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation");
        }
        return super.postProcessAfterInstantiation(bean, beanName);
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if ("animal".equals(beanName)) {
            System.out.println("InstantiationAwareBeanPostProcessor.postProcessPropertyValues");
        }
        return pvs;
    }

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

        return super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return super.postProcessAfterInitialization(bean, beanName);
    }
}

定义一个MyBeanPostProcessor并实现BeanPostProcessor接口

public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(beanName.equals("animal")){
            Animal animal=(Animal)bean;
            System.out.println("调用MyBeanPostProcessor.postProcessAfterInitialization(): "+animal);
        }
        return bean;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(beanName.equals("animal")){
            Animal animal=(Animal)bean;
            System.out.println("调用MyBeanPostProcessor.postProcessBeforeInitialization(): "+animal);
        }
        return bean;
    }
}

编写xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">

    <bean id="animal" class="com.rookie.bigdata.factory.domain.Animal" destroy-method="myDestory" init-method="myInit">
        <property name="name" value="哈士奇"></property>
        <property name="age" value="3"></property>
    </bean>

</beans>

编写测试类

public class BeanFactoryMain {

    public static void main(String[] args) {

        ResourcePatternResolver resolver=new PathMatchingResourcePatternResolver();
        Resource resource = resolver.getResource("classpath:beanfactory/beans.xml");

        DefaultListableBeanFactory factory=new DefaultListableBeanFactory();
        XmlBeanDefinitionReader reader=new XmlBeanDefinitionReader(factory);
        reader.loadBeanDefinitions(resource);

        Person person = (Person)factory.getBean("person");

        System.out.println(person);

    }

}

这样在运行测试类,就可以看到BeanFactory的整个运行的声明周期过程啦。

原文地址:https://www.cnblogs.com/haizhilangzi/p/11110474.html

时间: 2024-11-08 22:57:13

Spring IoC容器-BeanFactory的相关文章

spring——IOC容器BeanFactory和ApplicationContext对比

Spring IoC容器的初始化过程

Spring IoC容器的初始化包括 BeanDefinition的Resource定位.载入和注册 这三个基本的过程.IoC容器的初始化过程不包含Bean依赖注入的实现.Bean依赖的注入一般会发生在第一次通过getBean向容器索取Bean的时候. 先看以下代码: ApplicationContext context = new ClassPathXmlApplicationContext("ioc.xml"); Car car = (Car) context.getBean(&q

MyEclipse Spring 学习总结一 Spring IOC容器

一.Spring IOC容器---- Spring AllicationContext容器 程序的结构如下: 1.首先在MyEclipse 创建创建Java Project 2.创建好后,添加sping支持.在project上右击, MyEclipse->Add spring Capabilities. 3.之后会自动生成applicationContent.xml文件 1)创建HelloWorld.java public class HelloWorld { private String me

介绍 Spring IoC 容器和 bean

简介 本章涵盖了 Spring Framework实现控制翻转 (IoC) 的原则. IoC 有时也被称为依赖注入 (DI).这是一个对象定义他们依赖的过程,其中对象之间的相关性,也就是说,它们一起工作,只能通过构造函数参数,参数工厂方法或设置在其构造后的对象实例或者是从一个工厂方法返回的对象实例的属性上.容器在创建的 bean 注入这些依赖.这个过程是根本的反转,因此称为控制反转(IoC),bean 本身通过直接构造类,或作为 Service Locator(服务定位器)模式的机制,来控制其依

自己实现Spring IoC容器(四)IoC容器的Bug

Bug的发现 之前我自己写了一个类似Spring中的IoC容器自己实现Spring IoC容器(三)完成IoC容器,然后最近想在这个项目基础上把Spring的AOP也实现一下,然后就悲剧的发现了一句错误代码-- 这个错误代码就在edu.jyu.core.ClassPathXmlApplicationContext类的Object createBeanByConfig(Bean bean)方法中,下面是这个方法 /** * 根据bean的配置信息创建bean对象 * * @param bean *

Spring IOC 容器源码分析 - 创建单例 bean 的过程

1. 简介 在上一篇文章中,我比较详细的分析了获取 bean 的方法,也就是getBean(String)的实现逻辑.对于已实例化好的单例 bean,getBean(String) 方法并不会再一次去创建,而是从缓存中获取.如果某个 bean 还未实例化,这个时候就无法命中缓存.此时,就要根据 bean 的配置信息去创建这个 bean 了.相较于getBean(String)方法的实现逻辑,创建 bean 的方法createBean(String, RootBeanDefinition, Obj

Spring IOC 容器源码分析 - 余下的初始化工作

1. 简介 本篇文章是"Spring IOC 容器源码分析"系列文章的最后一篇文章,本篇文章所分析的对象是 initializeBean 方法,该方法用于对已完成属性填充的 bean 做最后的初始化工作.相较于之前几篇文章所分析的源码,initializeBean 的源码相对比较简单,大家可以愉快的阅读.好了,其他的不多说了,我们直入主题吧. 2. 源码分析 本章我们来分析一下 initializeBean 方法的源码.在完成分析后,还是像往常一样,把方法的执行流程列出来.好了,看源码

Spring IoC容器实现

1,Spring的两种IoC容器 BeanFactory 基础类型的IoC容器: 采用延迟初始化策略(容器初始化完成后并不会创建bean的对象,只有当收到初始化请求时才进行初始化): 由于延迟初始化,因此启动速度较快,占用资源较少: ApplicationContext 在BeanFactory的基础上,增加了更为高级的特定:事件发布.国际化等: 在容器启动时便完成所有bean的创建: 启动时间较长,占用资源更多: 2,IoC容器的主要类/接口介绍 1)BeanFactory 它是一个接口,提供

1.3浅谈Spring(IOC容器的实现)

这一节我们来讨论IOC容器到底做了什么. 还是借用之前的那段代码 ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("beans.xml"); Car car =app.getBean(Car.class); System.out.println(car.getBrand()+","+car.getDesc()); 这里ClassPathXmlApplicationCont