Spring Bean生命周期及线程安全 待我称王封你为后i 2022-12-10 07:06 90阅读 0赞 **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的生命周期 # ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppa2UxMTIzMQ_size_16_color_FFFFFF_t_70_pic_center] ## 生命周期可以简述为以下九步: ## **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 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppa2UxMTIzMQ_size_16_color_FFFFFF_t_70_pic_center 1][] 原理步骤2 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppa2UxMTIzMQ_size_16_color_FFFFFF_t_70_pic_center 2] 原理步骤3 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppa2UxMTIzMQ_size_16_color_FFFFFF_t_70_pic_center 3] # 二、实现ImplementsBeanFactoryAware,BeanNameAware,InitializingBean,DisposableBean后生命周期代码验证 # ## 生命周期 ## ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppa2UxMTIzMQ_size_16_color_FFFFFF_t_70_pic_center 4] ## 代码验证 ## 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"); this.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、执行结果如下 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppa2UxMTIzMQ_size_16_color_FFFFFF_t_70_pic_center 5] 这篇文也不错,值得一读 [Spring中bean的生命周期(易懂版)][Spring_bean] **参考资料** [Spring Bean的生命周期(非常详细)][Spring Bean] [Spring 了解Bean的一生(生命周期)][Spring _Bean] [JAVA面试题:Spring中bean的生命周期][JAVA_Spring_bean] [Spring注解之后置处理器][Spring] [Spring后置处理器BeanPostProcessor用法与原理][Spring_BeanPostProcessor] [生命周期-BeanPostProcessor原理][-BeanPostProcessor] [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppa2UxMTIzMQ_size_16_color_FFFFFF_t_70_pic_center]: /images/20221123/fc81305cacee4db9b2a4788d03f1f5cd.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppa2UxMTIzMQ_size_16_color_FFFFFF_t_70_pic_center 1]: /images/20221123/fbe9bf20c0b24d329028ccc2db44e579.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppa2UxMTIzMQ_size_16_color_FFFFFF_t_70_pic_center 2]: /images/20221123/1babe6cec4c84c8c9b07ebf4ede91380.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppa2UxMTIzMQ_size_16_color_FFFFFF_t_70_pic_center 3]: /images/20221123/99d1504fe7854630b827d16e974888ed.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppa2UxMTIzMQ_size_16_color_FFFFFF_t_70_pic_center 4]: /images/20221123/dd03cb89f19349aa8dcd3212b0f8b26b.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppa2UxMTIzMQ_size_16_color_FFFFFF_t_70_pic_center 5]: /images/20221123/a70a49387d554dda938b117b6be7e887.png [Spring_bean]: https://keafmd.blog.csdn.net/article/details/112684756 [Spring Bean]: https://www.cnblogs.com/zrtqsk/p/3735273.html [Spring _Bean]: https://blog.csdn.net/w_linux/article/details/80086950 [JAVA_Spring_bean]: https://blog.csdn.net/weixin_34174105/article/details/85739351 [Spring]: https://blog.csdn.net/qq_38526573/article/details/88086752 [Spring_BeanPostProcessor]: https://blog.csdn.net/baidu_37107022/article/details/89006390 [-BeanPostProcessor]: https://blog.csdn.net/qq_36154832/article/details/102519977
还没有评论,来说两句吧...