Bean,就是由 IOC 容器初始化、装配及管理的对象。
在IOC容器启动之后,并不会马上就实例化相应的bean,此时容器仅仅拥有所有对象的BeanDefinition(BeanDefinition:是容器依赖某些工具加载的XML配置信息进行解析和分析,并将分析后的信息编组为相应的BeanDefinition)。只有当getBean()调用时才是有可能触发Bean实例化阶段的活动

因为当对应某个bean定义的getBean()方法第一次被调用时,不管是显示的还是隐式的,Bean实例化阶段才会被触发。第二次被调用则会直接返回容器缓存的第一次实例化完的对象实例(因为默认是singleton单例,当然,这里的情况prototype类型的bean除外)

Spring的bean默认scope属性为singleton,即单例的,所有线程都共享一个单例实例Bean,存在资源的竞争,有线程安全问题。
如果设置@Scope(“prototype”),则每次都会创建新对象,不存在线程安全问题。

public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
        Count count = context.getBean("count", Count.class);
        for(int i=0;i<10000;i++){
            Thread t = new Thread(()->{
               count.add();//让成员变量count++
            });
            t.start();
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(count.count);//预期值10000,有count值小于10000的情况
    }

如何实现线程安全
1.同步代码块/同步方法
2.ThreadLocal,提供了线程的局部变量,实现线程的数据隔离

一、Bean的生命周期

spring beanDefinitionMap 死锁_bean

生命周期可以简述为以下九步:

1:实例化bean对象(通过构造方法或者工厂方法,也就是我们常说的new)
2:设置对象属性(setter等)(依赖注入,也就是IOC注入)
3:如果Bean实现了BeanNameAware接口,调用Bean的setBeanName()方法传递Bean的ID(和下面的一条均属于检查Aware接口)
4:如果Bean实现了BeanFactoryAware接口(获取当前bean factory这也可以调用容器),工厂调用setBeanFactory()方法传入工厂自身
5:将Bean实例传递给Bean的前置处理器的postProcessBeforeInitialization(Object bean, String beanname)方法
6:调用Bean的初始化方法
7:将Bean实例传递给Bean的后置处理器的postProcessAfterInitialization(Object bean, String beanname)方法
8:使用Bean
9:容器关闭之前,调用Bean的销毁方法

相关接口作用

BeanNameAware接口作用

可以获取容器中bean的名称,为了让自身Bean能够感知到,就是获取到自身在Spring容器中的id或name属性

BeanPostProcessor接口作用

在Bean对象在实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑。即对创建出来的bean进行验证或者proxy,然后得到包装的bean。注意是Bean实例化完毕后及依赖注入完成后触发的。

bean的后置处理器BeanPostProcessor接口中两个方法:
postProcessBeforeInitialization:实例化、依赖注入完毕,在调用显示的初始化之前完成一些定制的初始化任务
postProcessAfterInitialization:实例化、依赖注入、初始化完毕时执行

BeanPostProcessor原理

1.populateBean(beanName, mbd, instanceWrapper);//给bean进行属性赋值
2.调用initializeBean方法,执行后置处理器和指定的初始化方法。(详细过程见下面源码)
3.后置处理器BeanPostProcessor执行过程是,遍历得到容器中所有的BeanPostProcessor;挨个执行beforeInitialization,一但返回null,跳出for循环,不会执行后面的BeanPostProcessor.postProcessorsBeforeInitialization

BeanPostProcessor原理图示解释

原理步骤1

spring beanDefinitionMap 死锁_bean_02


原理步骤2

spring beanDefinitionMap 死锁_spring_03


原理步骤3

spring beanDefinitionMap 死锁_System_04

二、实现ImplementsBeanFactoryAware,BeanNameAware,InitializingBean,DisposableBean后生命周期代码验证

生命周期

spring beanDefinitionMap 死锁_实例化_05

代码验证

1、spring-bean.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:tx="http://www.springframework.org/schema/tx"      
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans  
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/context/spring-tx.xsd
        ">    
   
	<bean id="beanPostProcessor"
		class="com.springtest.MyBeanPostProcessor">
	</bean>

	<bean id="instantiationAwareBeanPostProcessor"
		class="com.springtest.MyInstantiationAwareBeanPostProcessor">
	</bean>

	<bean id="beanFactoryPostProcessor"
		class="com.springtest.MyBeanFactoryPostProcessor">
	</bean>
        <!-- 
	<bean id="person" class="com.springtest.Person"
		init-method="myInit" destroy-method="myDestory" scope="singleton"
		p:name="张三" p:address="深圳" p:phone="110"/> 
		//这种加p命名空间方式,必须在xml头部添加  xmlns:p="http://www.springframework.org/schema/p"
	-->	
	<!-- init-method:指定初始化的方法   ;  destroy-method:指定销毁的方法 -->
	<bean id="person" class="com.springtest.Person"
		init-method="myInit" destroy-method="myDestory" scope="singleton"> 
	   <property name="name" value="张三"/>
       <property name="address" value="深圳"/>
       <property name="phone" value="120"/> 
    </bean>   
</beans>

2、Person.java

package com.springtest;

import org.springframework.beans.BeansException;
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 Person implements  BeanFactoryAware,BeanNameAware,InitializingBean,DisposableBean{
    
	private String name;
	private String address;
	private int phone;
	
	private BeanFactory beanFactory;
	private String beanName;
	
    public Person() {
        System.out.println("【构造器】调用Person的构造器实例化");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("【属性注入】注入属性name");
         = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        System.out.println("【属性注入】注入属性address");
        this.address = address;
    }

    public int getPhone() {
        return phone;
    }

    public void setPhone(int phone) {
        System.out.println("【属性注入】注入属性phone");
        this.phone = phone;
    }

    @Override
    public String toString() {
        return "Person [address=" + address + ", name=" + name + ", phone=" + phone + "]";
    }

    // 这是BeanFactoryAware接口方法
    @Override
    public void setBeanFactory(BeanFactory arg0) throws BeansException {
        System.out.println("【BeanFactoryAware接口】调用BeanFactoryAware.setBeanFactory()方法");
        this.beanFactory = arg0;
    }

    // 这是BeanNameAware接口方法
    @Override
    public void setBeanName(String arg0) {
        System.out.println("【BeanNameAware接口】调用BeanNameAware.setBeanName()方法");
        this.beanName = arg0;
    }

    // 这是InitializingBean接口方法
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("【InitializingBean接口】调用InitializingBean.afterPropertiesSet()方法");
    }
    

    // 这是DiposibleBean接口方法
    @Override
    public void destroy() throws Exception {
        System.out.println("【DiposibleBean接口】调用DiposibleBean.destory()方法");
    }

    // 通过<bean>的init-method属性指定的初始化方法
    public void myInit() {
        System.out.println("【init-method】调用<bean>的init-method属性指定的初始化方法");
    }

    // 通过<bean>的destroy-method属性指定的初始化方法
    public void myDestory() {
        System.out.println("【destroy-method】调用<bean>的destroy-method属性指定的初始化方法");
    }
}

3、后置处理器 MyBeanPostProcessor.java

package com.springtest;


import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * bean的后置处理器
 * 分别在bean的初始化前后对bean对象提供自己的实例化逻辑
 * postProcessAfterInitialization:初始化之后对bean进行增强处理
 * postProcessBeforeInitialization:初始化之前对bean进行增强处理
 * 
 */
public class MyBeanPostProcessor implements BeanPostProcessor {

    public MyBeanPostProcessor() {
        super();
        System.out.println("这是BeanPostProcessor实现类构造器!!");
    }

    @Override
    public Object postProcessAfterInitialization(Object arg0, String arg1)
            throws BeansException {
        System.out.println("BeanPostProcessor接口方法postProcessAfterInitialization对属性进行更改!");
        return arg0;
    }

    @Override
    public Object postProcessBeforeInitialization(Object arg0, String arg1)
            throws BeansException {
        System.out.println("BeanPostProcessor接口方法postProcessBeforeInitialization对属性进行更改!");
        return arg0;
    }
}

4、MyInstantiationAwareBeanPostProcessor.java

package com.springtest;

import java.beans.PropertyDescriptor;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;

public class MyInstantiationAwareBeanPostProcessor extends
        InstantiationAwareBeanPostProcessorAdapter {

    public MyInstantiationAwareBeanPostProcessor() {
        super();
        System.out.println("这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!");
    }

    // 接口方法、实例化Bean之前调用
    @Override
    public Object postProcessBeforeInstantiation(Class beanClass,
            String beanName) throws BeansException {
        System.out.println("InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法");
        return null;
    }

    // 接口方法、实例化Bean之后调用
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println("InstantiationAwareBeanPostProcessor调用postProcessAfterInitialization方法");
        return bean;
    }

    // 接口方法、设置某个属性时调用
    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs,
            PropertyDescriptor[] pds, Object bean, String beanName)
            throws BeansException {
        System.out.println("InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法");
        return pvs;
    }
}

5、MyBeanFactoryPostProcessor.java

package com.springtest;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    public MyBeanFactoryPostProcessor() {
        super();
        System.out.println("这是BeanFactoryPostProcessor实现类构造器!!");
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0)
            throws BeansException {
        System.out.println("BeanFactoryPostProcessor调用postProcessBeanFactory方法");
        BeanDefinition bd = arg0.getBeanDefinition("person");
        bd.getPropertyValues().addPropertyValue("phone", "110");
    }

}

6、测试类BeanLifeCycleTest.java

package com.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.springtest.Person;

public class BeanLifeCycleTest {

    public static void main(String[] args) {

        System.out.println("现在开始初始化容器!");

        ApplicationContext ac = new ClassPathXmlApplicationContext("spring-bean.xml");
        System.out.println("容器初始化成功");
        //得到Preson,并使用
        Person person = ac.getBean("person",Person.class);
        System.out.println("使用Bean:"+person);

        System.out.println("现在开始关闭容器!");
        ((ClassPathXmlApplicationContext)ac).registerShutdownHook();
    }
}

7、执行结果如下

spring beanDefinitionMap 死锁_spring_06