• Spring IOC


    1  什么是ioc:ioc就是将对象的创建及对象之间的关系交给容器管理

    2 BeanFactory与ApplicationContext,及FactoryBean

         一般来说,我们称BeanFactory为ioc容器 而ApplicationContext成为Spring容器。

      ApplicationContext主要的实现类是ClassPathXmlApplicationContext和FileSystemXmlApplicationContext,前者默认从类路径加载配置文件,后者默认从文件系统加载配置文件。

    在获取ApplicationContext实例后,就可以像BeanFactory一样调用getBean(beanName)方法来获取bean了,ApplicationContext和BeanFactory初始化有一个重大区别:BeanFactory初始化容器时 并未实例化bean,直到第一次访问某个bean时才实例化目标bean,

    而ApplicationContext 则在初始化应用上下文时就初始化所有单实例的bean,因此ApplicationContext的初始化时间要比BeanFactory的初始化长一些,后面要使用ApplicationContext的bean时 可以直接去缓存中获取bean。

      FactoryBean是一种特殊的bean接口,其作用也是创建bean,包含FactoryBean<T> 包含三个方法

      boolean isSingleton(); 返回所创建的bean是否是单例的,

      T getObject() 返回又FactoryBean所创建的bean实例,如果isSingleton方法返回true,那么bean实例将会被放到spring容器的缓存池中,

      Class<?> getObejctType();返回创建bean的类型。

      当一个需要被注入到容器的bean实现了FactoryBean接口时,通过getBean()方法返回的不是FactoryBean本身,而是FactoryBean.getObject()返回的对象,也就是说FactoryBean.getObject()代理了getBean()方法。

    3 Bean的生命周期

      BeanFactory中的bean的生命周期

    package com.bujiang.magic;
    
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.BeanFactoryAware;
    import org.springframework.beans.factory.BeanNameAware;
    import org.springframework.beans.factory.DisposableBean;
    import org.springframework.beans.factory.InitializingBean;
    
    public class Car implements BeanFactoryAware ,BeanNameAware,InitializingBean,DisposableBean{
        
        private String brand;
        private String color;
        private int maxSpeed;
        private BeanFactory beanFactory;
        private String beanName;
        public Car() {
            System.out.println("调用Car的构造方法");
        }
        public String getBrand() {
            return brand;
        }
        public void setBrand(String brand) {
            System.out.println("调用setBrand() 方法");
            this.brand = brand;
        }
        public String getColor() {
            return color;
        }
        public void setColor(String color) {
            this.color = color;
        }
        public int getMaxSpeed() {
            return maxSpeed;
        }
        public void setMaxSpeed(int maxSpeed) {
            this.maxSpeed = maxSpeed;
        }
        public BeanFactory getBeanFactory() {
            return beanFactory;
        }
        public void setBeanFactory(BeanFactory beanFactory) {
            System.out.println("调用BeanFactoryAware的setBeanFactory方法");
            this.beanFactory = beanFactory;
        }
        public String getBeanName() {
            return beanName;
        }
        public void setBeanName(String beanName) {
            System.out.println("调用BeanNameAware的setBeanName方法");
            this.beanName = beanName;
        }
        @Override
        public void destroy() throws Exception {
            System.out.println("调用DisposableBean的destroy方法");
            
        }
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("调用InitializingBean的afterPropertiesSet方法");
            
        }
        
        public void myInit() {
            System.out.println("调用car的init-method指向的myInit方法");
        }
        
        public void myDestroy() {
            System.out.println("调用car的destroy-method指向的myDestroy方法");
        }
        @Override
        public String toString() {
            return "Car [brand=" + brand + ", color=" + color + ", maxSpeed=" + maxSpeed + ", beanFactory=" + beanFactory
                    + ", beanName=" + beanName + "]";
        }
        
        
    
    }
    package com.bujiang.magic;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    
    public class MyBeanPostProcessor  implements BeanPostProcessor{
        public Object postProcessBeforeInitialization(Object bean,String beanName)throws BeansException {
            if(beanName.equals("car")) {
                Car car = (Car)bean;
                if(car.getColor()==null) {
                    System.out.println("调用MyBeanPostProcessor的postProcessBeforeInitialization方法,为bean设置属性color,为黑黑黑");
                    car.setColor("黑黑黑");
                }
            }
            return bean;
        }
        
        public Object postProcessAfterInitialization(Object bean,String beanName)throws BeansException {
            if(beanName.equals("car")) {
                Car car = (Car)bean;
                if(car.getMaxSpeed()>=200) {
                    System.out.println("调用MyBeanPostProcessor的postProcessAfterInitialization方法,为bean设置属性MaxSpeed,为999");
                    car.setMaxSpeed(999);
                }
            }
            return bean;
        }
    }
    package com.bujiang.magic;
    
    import java.beans.PropertyDescriptor;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.PropertyValues;
    import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
    
    public class MyInsttabtiationAwareBeanPostProcessor  implements InstantiationAwareBeanPostProcessor{
        
        public Object postProcessBeforeInstantiation(Class beanClass,String beanName) throws BeansException {
            if("car".equals(beanName)) {
                System.out.println("调用MyInsttabtiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法");
            }
            return null;
        }
        
        public boolean postProcessAfterInstantiation(Object bean,String beanName) throws BeansException {
            if("car".equals(beanName)) {
                System.out.println("调用MyInsttabtiationAwareBeanPostProcessor的postProcessAfterInstantiation方法");
            }
            return true;
        }
        
        public PropertyValues postProcessPropertyValues(PropertyValues pvs,PropertyDescriptor[] pds,Object bean,String beanName)throws BeansException {
            if("car".equals(beanName)) {
                System.out.println("调用MyInsttabtiationAwareBeanPostProcessor的postProcessPropertyValues方法");
            }
            return pvs;
        }
    
    }
    <?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:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
           xmlns:p="http://www.springframework.org/schema/p"
        xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd" default-autowire="byName">
        
        <bean id="car" class="com.bujiang.magic.Car" init-method="myInit" destroy-method="myDestroy" p:brand="红旗CA72" p:maxSpeed="200" scope="singleton" />
        <!-- <bean id="car" class="com.bujiang.magic.Car" init-method="myInit" destroy-method="myDestroy" p:brand="红旗CA72" p:maxSpeed="200" scope="prototype" /> -->
    </beans>
    package com.bujiang.magic;
    
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.config.ConfigurableBeanFactory;
    import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
    import org.springframework.core.io.ClassPathResource;
    import org.springframework.core.io.Resource;
    
    public class BeanLifeCycle {
        private static void lifeTest() {
            //加载配置文件并启动容器
            Resource res = new ClassPathResource("com/bujiang/magic/beans.xml");
            BeanFactory bf = new DefaultListableBeanFactory();
            XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader((DefaultListableBeanFactory)bf);
            reader.loadBeanDefinitions(res);
            
            //向容器注册MyBeanPostProcessor后置处理器,如果容器不注册那么BeanPostProcessor所有的方法都不执行
            ((ConfigurableBeanFactory) bf).addBeanPostProcessor(new MyBeanPostProcessor());
            //向容器注册MyInsttabtiationAwareBeanPostProcessor后置处理器,如果容器不注册那么InstantiationAwareBeanPostProcessor所有的方法都不执行
            ((ConfigurableBeanFactory) bf).addBeanPostProcessor(new MyInsttabtiationAwareBeanPostProcessor());
            
            //第一次从容器中获取bean对象,将触发实例化bean的生命周期方法的调用
            Car car1 = (Car) bf.getBean("car");
            System.out.println(car1.toString());
            car1.setColor("红色");
            
            //第二次从容器中获取bean,直接从缓存中获取,不会触发生命周期方法
            Car car2 = (Car) bf.getBean("car");
            System.out.println("car1=car2?"+(car1==car2));
            
            //关闭容器
            ((DefaultListableBeanFactory)bf).destroySingletons();
        }
        
        public static void main(String[] args) {
            lifeTest();
        }
    
    }

    输出结果

    调用MyInsttabtiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法
    调用Car的构造方法
    调用MyInsttabtiationAwareBeanPostProcessor的postProcessAfterInstantiation方法
    调用MyInsttabtiationAwareBeanPostProcessor的postProcessPropertyValues方法
    调用setBrand() 方法
    调用BeanNameAware的setBeanName方法
    调用BeanFactoryAware的setBeanFactory方法
    调用MyBeanPostProcessor的postProcessBeforeInitialization方法,为bean设置属性color,为黑黑黑
    调用InitializingBean的afterPropertiesSet方法
    调用car的init-method指向的myInit方法
    调用MyBeanPostProcessor的postProcessAfterInitialization方法,为bean设置属性MaxSpeed,为999
    Car [brand=红旗CA72, color=黑黑黑, maxSpeed=999, beanFactory=org.springframework.beans.factory.support.DefaultListableBeanFactory@11c20519: defining beans [car]; root of factory hierarchy, beanName=car]
    car1=car2?true
    调用DisposableBean的destroy方法
    调用car的destroy-method指向的myDestroy方法

      当通过getBean获取bean时:

      1 调用InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation()方法

      2 调用调用构造函数或者其他方式实例化bean

      3 调用InstantiationAwareBeanPostProcessor接口的postProcessAfterInstantiation()方法

      4 调用InstantiationAwareBeanPostProcessor接口的postProcessPropertyValues()方法     

      5 调用bean的设置属性值的方法 setXXX()  

      6 调用BeanFactoryAware的setBeanName()方法

      7 调用BeanFactoryAware的setBeanFactory()方法

      8 调用BeanPostProcessor的postProcessBeforeInitialization方法

      9 调用InitializingBean的afterPropertiesSet方法

      10 调用bean指定的init-method方法

      11 调用BeanPostProcessor的postProcessAfterInitialization方法

      12如果bean的作用范围是多例(prototype),那么将bean返回给调用者 Spring不再管理这个bean的生命周期,如果是单例(singleton) 则将bean放入到ioc容器的缓存池中,并将bean的引用返回给调用者,ioc容器继续管理这个bean的生命周期

      13 当容器关闭时,触发DisposableBean的destroy方法

      14 执行bean的destroy-method指定的方法。

     以上方法可以分为以下4类

      1 Bean自身的方法:如构造方法,setXXX方法 init-method指定的方法 destroy-method指定的方法

         2 Bean级别生命周期接口方法: BeanFactoryAware ,BeanNameAware,InitializingBean,DisposableBean接口方法,执行方法由bean类直接实现

      3 容器级别的生命周期方法:如BeanPostProcessor,InstantiationAwareBeanPostProcessor的方法,这些方法一般成为类的后置处理器,当IOC容器创建任何bean的时候,这些后置处理器都会起作用,就是说这些处理器的影响是全局性的

      4 工厂后处理器接口方法,工厂后处理器也是容器级的,在应用上下文装配配置文件后立即调用

      

    ApplicationContext中的bean的生命周期

      bean在ApplicationContext的生命周期与在BeanFactory中的生命周期类似,不同的是如果bean 实现了ApplicationContextAware接口,则会增加该接口的setApplicationContext方法,该方法在上面生命周期的第七步之后,第八步之前。ApplicationContext与BeanFactory的另外一个最大的不同是 前者会利用java反射机制自动识别配置文件中定义的工厂后置处理器,并自动将他们注册到上下文,而后者需要手动的addBeanPostProcessor方法才行,因此应用开发中普遍使用ApplicationContext而不是BeanFactory。如果配置文件定义了多个工厂后置处理器,那么让它们实现import org.springframework.core.Ordered接口,如果不实现这个接口那么,那么的先后顺序将由它们在xml中定义的位置确定,先定义的先执行。

    IOC装配bean

      

      Spring启动时读取应用程序提供的bean的配置信息,并在容器中生成一份相应的bean注册表,然后根据注册表实例化bean,装配好bean之间的依赖关系,为应用提供运行环境。Bean的配置信息就是bean的元数据信息,元数据信息在容器内部对应的是一个个BeanDefinition形成的注册表,Spring通过元数据和外部bean定义实现解耦。

    依赖注入,spring支持两种依赖注入的方式(属性注入和构造函数注入),此外 还支持工厂方法注入。

      属性注入,属性注入是通过setXXX方法将bean的属性或者依赖的对象注入到bean中,属性注入比较于构造器注入是更灵活的。属性注入要求Bean提供一个默认的无参构造函数,并且要注入的属性提供setXXX方法,Spring先利用构造方法实例化Bean对象,然后利用反射方式调用Setter方法注入属性值。使用属性注入时,Spring 只会检查bean中是否有对应的setter方法,至于Bean中是否有这个属性则不做要求,对于属性注入时的属性名,spring希望变量前两个字母要么全部大写,要么全部小写,如brand,IDCode是合法的,而iC,iDCard是不合法的,当我们使用不合法的属性名,启动Spring 会报Invalid property 'iDCard' of bean class,

      构造函数注入,相较与属性注入,构造函数注入比较繁琐,这里不做介绍

      工厂方法注入

        1 静态工厂方法注入

        <bean id = "carFactory" class="xxxx.CarFactory"></bean>
        <!-- 由于普通工厂方法是非静态的,所以需要先实例化工厂类 -->
        <bean id="car" factory-bean="carFactory" factory-method="createCar"></bean>

        2 静态工厂方法注入

        <!-- 由于普通工厂方法是静态的,所以可以直使用方法方法注入 -->
        <bean id="car" factory-method="xxx.CarFactory。createCar"></bean>

    Bean的作用域

      singleton

        传统开发中,由于dao类中持有Connection这个非现场安全的变量,因此往往是不能采用单例模式的,但是spring 利用aop和ThreadLocal 对非线程安全的变量进行了特殊的处理(这个后面再说),使这些变成了线程安全的类,这哥原因也是为什么大部分bean都能以单例模式运行的原因。

      prototype

        这种是非单例的模式,spring容器将这种bean初始化之后交给调用者,其后续的生命周期spring不再管理。

      其他作用域 request,session,gloalSession 这些与WebApplicationContext相关的作用域

    注解

    @Component 等价于一下注解配置

    <bean id = "carFactory" class="xxxx.CarFactory"></bean>

    此外spring还提供一下三个注解,功能等价于@Component ,作用仅仅是表名各个层中的bean的用途意义,完全可以用@Component替代他们

    @Respository,@Service ,@Controller。

    @Autowired 自动装配,默认使用byType方式,按照类型匹配来注入bean。@Autowired 支持在属性和方法上使用,作用都是自动注入。

    @Resource ,@Inject ,这两者与@Autowired 作用基本一致,@Resource是byName注入,@Inject 用的比较少

    @Qualifier 指定注入bean的名称。、

    基于java类的注解配置

    @Configuration 这个注解的作用是将一个pojo标注为spring配置类,

    @Bean 这个注解是返回一个bean,bean的名称默认是方法名,

  • 相关阅读:
    内存溢出
    Spring-bean的循环依赖以及解决方式
    JUC中Lock和ReentrantLock介绍及源码解析
    RocketMQ阅读注意
    RocketMQ环境搭建
    HSF源码阅读
    最近找工作,有招JAVA开发的可以联系我,如果不嫌弃我2年前用C,也可以联系我
    Spring Extensible XML
    MySQL主主+Keepalived架构安装部署
    记录一则数据库死锁故障的分析过程
  • 原文地址:https://www.cnblogs.com/tjqBlog/p/10027218.html
Copyright © 2020-2023  润新知