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的生命周期

生命周期可以简述为以下九步:
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

原理步骤2

原理步骤3

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

代码验证
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、执行结果如下

















