精通Spring 4.x企业应用开发实战——IoC(三)
2018-03-01 17:53
585 查看
IoC:控制反转,spring容器的内核——AOP、声明式事务都是在此基础上来的
理解IoC:某一接口具体实现的选择控制权从调用类中移除,转交给第三方决定,也就是由Spring容器借由Bean配置来进行控制
对IoC的理解:
IoC三种类型:
1、构造函数注入:通过调用类的构造函数,将接口实现类通过构造函数变量传入。
MoAttack:通过构造函数注入geli的饰演者
public class MoAttack {
private Geli geli;
/**
* 注入geli的具体饰演者
* @param geli
*/
public MoAttack(Geli geli){
this.geli = geli;
}
public void cityGateAsk(){
geli.response();
}
}Director:通过构造函数注入geli的饰演者
public class Director {
public void director(){
//指定角色的饰演者
Geli geli = new LiDeHua();
//注入具体饰演者到剧本中
MoAttack moAttack = new MoAttack(geli);
moAttack.cityGateAsk();
}
} 2、属性注入:通过Setter方法完成调用类所需的注入
MoAttack:通过Setter方法注入geli饰演者
/**
* 通过Setter方法注入geli的饰演者
* @param geli
*/
public void setGeli(Geli geli){
this.geli = geli;
}
public void cityGateAsk(){
geli.response();
}Director:调用属性Setter方法注入
//调用属性Setter方法注入
moAttack.setGeli(geli);
moAttack.cityGateAsk(); 3、 接口注入 :效果和属性注入无本质区别
通过容器完成依赖关系的注入
<?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.xsd">
<!--实现类实例化-->
<bean id="geli" class="com.smart.IoC.LiDeHua"/>
<bean id="MoAttack" class="com.smart.IoC.MoAttack"
p:geli-ref="geli">
</bean><!--通过geli-ref建立依赖关系-->
</beans>Java基础:
Java允许通过程序化的方式间接对Class进行操作。Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获知Class的结构信息,如构造函数、属性、方法。
public class ReflectTest {
public static Car initByDefaultConst() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//①通过类装载器获取Car对象
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Class clazz = classLoader.loadClass("com.smart.reflect.Car");
//②获取类的默认构造器对象并通过它实例化Car
Constructor constructor = clazz.getDeclaredConstructor((Class[]) null);
Car car = (Car) constructor.newInstance();
//③通过反射方法设置属性
Method setBrand = clazz.getMethod("setBrand",String.class);
setBrand.invoke(car,"红旗轿车");
Method setColor = clazz.getMethod("setColor",String.class);
setColor.invoke(car,"黑色");
Method setMaxSpeed = clazz.getMethod("setMaxSpeed",Integer.class);
123f2
setMaxSpeed.invoke(car,"黑色");
return car;
}
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Car car = initByDefaultConst();
car.introduce();
}
}该例中使用的反射类:ClassLoader、Class、 Constructor、Method
类装载器ClassLoader:通过寻找类的字节码文件并构造出类在JVM内部表示对象的组件.装载工作由其子类完成。
类件被装载解析后,在JVM内拥有一个对应的java.lang.Class类述对象,该类的实例都指向这个描述对象的引用,而类描述对象又拥有指向关联ClassLoader的引用。
Java反射机制:Class反射对象描述类语义结构,可以从Class对象中获取构造函数、成员变量、方法等类元素的反射对象,并通过这些反射对象对目标类进行操作。Java的反射体系保证了可以通过程序化的方式访问目标类中的所有元素,(对于private和protected成员变量和方法,只要JVM的安全机制允许,也可以通过反射进行调用。)
BeanFactory(IoC容器)和ApplicationContext(应用上下文或Spring容器)
Bean工厂是Spring框架最核心的接口,他提供了高级IoC的配置机制,使管理不同类型的Java对象成为可能
应用上下文建立再BeanFactory基础之上,提供了更多面向应用的功能。
BeanFactory是Spring框架的基础设施,面向Spring本身;ApplicationContext面向使用Spring框架的开发者,几乎所有的应用场合都可以直接使用ApplicationContext而非底层的BeanFactory
BeanFactory的类体系结构
BeanFactory最主要的方法getBean()——从容器中返回特定名称的Bean
通过BeanFactory启动IoC容器的时候,并不会初始化配置文件中的Bean,初始化动作发生再第一个调用时。对于单实例的Bean来说BeanFactory会缓存Bean实例,所以第二次使用getBean()获取Bean时,将直接从IoC容器的缓存中获取Bean实例。
ApplicationContext的类体系结构(ApplicationContext由BeanFactory派生出来)
ApplicationContext主要实现类是ClassPathXmlApplicationContext(从类路径下加载)和FileSystemXmlApplicationContext(从系统路径下加载)
ApplicationContext和BeanFactory初始化区别:BeanFactory初始化容器时并未实例化Bean,直到第一次访问某个Bean时才实例化目标Bean;ApplicationContext则在初始化应用上下文时就实例化所有单实例的Bean。
WebApplicationContext类体系结构:专门为web应用准备的,允许从相对于Web根目录的路径中装配配置文件完成初始化工作.
WebApplicationContext的初始化和ApplicationContext、BeanFactory有所区别,因为WebApplicationContext需要ServletContext实例,也就是必须在拥有web容器的前提下才能完成启动工作。(在web.xml中配置自启动的Servlet或定义web容器监听器)
Bean的生命周期
BeanFactory中Bean的生命周期图解
1)通过getBean()请求一个Bean时,如果容器注册了InstantiationAwareBeanPostProcessor 接口,则在Bean实例化之前调用接口的postProcessBeforeInstantiation()方法。
2)实例化Bean,如果容器注册了InstantiationAwareBeanPostProcessor 接口,Bean实例化之后,调用postProcessAfterInstantiation()方法。
3)如果Bean配置了属性信息,容器将配置值设置到Bean对应的属性中。在设置之前先调用InstantiationAwareBeanPostProcessor接口的postProcessPropertyValues()方法。
4)设置Bean的属性,
如果实现了BeanNameAware接口,则调用setBeanName()方法,将配置文件中该Bean的名称设置Bean中。
如果实现了BeanFactoryAware接口,则调用setBeanFactory()方法,将BeanFactory容器实例设置Bean中。
5)如果BeanFactory装配了BeanPostProcessor 后处理器,则将调用Object postProcessBeforeInstantiation(Object bean,String beanName)接口方法对Bean进行加工。
6)如果Bean实现了InitializingBean接口,则将调用接口的afterPropertiesSet()方法
7)如果<bean>中通过init-method属性定义了初始化方法,则将执行这个方法。
8)BeanPostProcessor后处理器定义了两个方法:①postProcessBeforeInstantiation()在 5)处调用;②Object postProcessBeforeInstantiation(),该方法调用时,容器再次获得对Bean进行加工处理的机会。
9)如果<bean>中指定Bean的范围为scope="protoType",则Bean返回给调用者,调用者负责Bean后续生命管理,Spring不再管理;若范围为scope="singleton",则将Bean放入Spring IoC容器的缓存池里,并将Bean的引用返回给调用者,Spring继续对这些Bean进行后续的生命管理。
10)对于scope="singleton"的情况,当容器关闭时,将触发对Bean后续生命周期的管理工作。如果Bean实现了DisposableBean接口,将调用Bean的destroy()方法。
11)对于scope="singleton"的Bean,如果通过<bean>的destroy-method属性指定了Bean的销毁方法,那么Spring将执行这个方法完成Bean资源的释放。
Bean的完整生命周期从Spring容器着手实例化Bean开始,直到最终销毁Bean。其中经历的关键点大致分为四类:
Bean自身的方法:如Bean调用构造函数实例化Bean、调用Setter设置Bean的属性值以及通过<bean>的init-method和destroy-method所指定的方法。
Bean级生命周期接口方法:BeanNameAware、BeanFacotyAware、InitializingBean和DisposableBean,这些接口方法由Bean直接实现。
容器级生命周期接口方法:图中带有
的步骤是由InstantiationAwareBeanPostProcessor和BeanPostProcessor两个接口实现的。称为实现类“后处理器”
工厂后处理器接口方法: 包括AspectJWeavingEnabler、CustomAutowireConfigurer、ConfigurationClassPostProcessor等方法,工厂后处理器也是容级的,在应用上下文装配配置文件后立即调用。
实例:
实现各种生命周期控制的Car
package com.smart.beanLifeCycle;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
/**
* @author chenpeng
* @date 2018/3/1 12:56
*/
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 void setBrand(String brand){
System.out.println("调用setBrand设置属性。");
this.brand = brand;
}
public void introduce(){
System.out.println("brand: "+brand+",color: "+color+",maxSpeed: "+maxSpeed);
}
/**
* BeanFactoryAware接口方法
* @param beanFactory
* @throws BeansException
*/
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("调用BeanFactoryAware.setBeanFactory()方法");
this.beanFactory = beanFactory;
}
/**
* BeanNameAware接口方法
* @param beanName
*/
public void setBeanName(String beanName) {
System.out.println("调用BeanNameAware.setBeanName()方法");
this.beanName = beanName;
}
/**
* InitializingBean接口方法
* @throws Exception
*/
public void destroy() throws Exception {
System.out.println("调用InitializingBean.afterPropertiesSet()方法");
}
/**
* DisposableBean接口方法
* @throws Exception
*/
public void afterPropertiesSet() throws Exception {
System.out.println("调用DisposableBean.destroy()方法");
}
/**
* 通过<bean>的init-method属性指定初始化方法
*/
public void myInit(){
System.out.println("调用init-method所指定的myInit(),将maxSpeed设置为240");
this.maxSpeed = 240;
}
/**
* 通过<bean>的destroy-method属性指定销毁方法
*/
public void myDestroy(){
System.out.println("调用destroy-method所指定的myDestroy()方法");
}
}
Car类分别实现了BeanFactoryAware,BeanNameAware,InitializingBean,DisposableBean这些Bean级的生命周期控制接口。
InstantiationAwareBeanPostProcessor实现类:
package com.smart.beanLifeCycle;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import java.beans.PropertyDescriptor;
/**
* @author chenpeng
* @date 2018/3/1 13:22
*/
public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter{
/**
*在实例化Bean前调用
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
//return super.postProcessBeforeInitialization(bean, beanName);
//对容器中的Car Bean进行处理
if("car".equals(beanName)){
System.out.println("InstantiationAware BeanPostProcessor. postProcessBeforeInstantiation");
}
return null;
}
/**
* 在实例化Bean后调用
*/
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
//return super.postProcessAfterInstantiation(bean, beanName);
//对容器中的Car Bean进行处理
if("car".equals(beanName)){
System.out.println("InstantiationAware BeanPostProcessor. postProcessAfterInstantiation");
}
return true;
}
/**
*在设置某个属性时调用
*/
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
//return super.postProcessPropertyValues(pvs, pds, bean, beanName);
//对容器中的Car Bean进行处理,还可以通过pdst入参进行过滤
if("car".equals(beanName)){
System.out.println("InstantiationAwareBeanPostProcessor. postProcessPropertyValues");
}
return pvs;
}
}
BeanPostProcessor实现类:
package com.smart.beanLifeCycle;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
* @author chenpeng
* @date 2018/3/1 13:40
*/
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("调用BeanPostProcessor.postProcessBeforeInitialization()," +
"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("调用BeanPostProcessor.postProcessAfterInitialization()," +
"将maxSpeed调整为200");
car.setMaxSpeed(200);
}
}
return bean;
}
}
beanLifeCycle.xml:配置Car
<?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.xsd"> <bean id="car" class="com.smart.beanLifeCycle.Car"
init-method="myInit"
destroy-method="myDestroy"
p:brand="红旗"
p:maxSpeed="200"/>
</beans>运行报错:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'car' defined in class path resource [beanLifeCycle.xml]: Invocation of init method failed; nested exception is java.lang.NullPointerException
发现书上代码有问题:
InstantiationAwareBeanPostProcessor接口注册返回对应的bean,不然报空,容器获取不到!
正确运行:
ApplicationContext中Bean的生命周期
Bean在应用上下文中的生命周期和在BeanFactory中的生命周期类似,不同的是:①如果Bean实现了ApplicationContextAware接口,会增加一个调用该接口的方法,setApplicationContext();②ApplicationContext可以利用Java反射机制自动识别出配置文件中定义的BeanPostProcessor、InitializationAwareBeanPostProcessor和BeanFactoryPostProcessor,并自动注册到应用上下文中,而BeanFactory则需要手动调用addBeanPostProcessor()方法进行注册。(开发中常使用ApplicationContext)
Bean的生命周期不但和其实现的接口有关还和Bean的作用范围有关。为了让Bean绑定在Spring框架上,推荐使用配置的方式而非接口的方式进行Bean的生命周期的控制。
理解IoC:某一接口具体实现的选择控制权从调用类中移除,转交给第三方决定,也就是由Spring容器借由Bean配置来进行控制
对IoC的理解:
IoC三种类型:
1、构造函数注入:通过调用类的构造函数,将接口实现类通过构造函数变量传入。
MoAttack:通过构造函数注入geli的饰演者
public class MoAttack {
private Geli geli;
/**
* 注入geli的具体饰演者
* @param geli
*/
public MoAttack(Geli geli){
this.geli = geli;
}
public void cityGateAsk(){
geli.response();
}
}Director:通过构造函数注入geli的饰演者
public class Director {
public void director(){
//指定角色的饰演者
Geli geli = new LiDeHua();
//注入具体饰演者到剧本中
MoAttack moAttack = new MoAttack(geli);
moAttack.cityGateAsk();
}
} 2、属性注入:通过Setter方法完成调用类所需的注入
MoAttack:通过Setter方法注入geli饰演者
/**
* 通过Setter方法注入geli的饰演者
* @param geli
*/
public void setGeli(Geli geli){
this.geli = geli;
}
public void cityGateAsk(){
geli.response();
}Director:调用属性Setter方法注入
//调用属性Setter方法注入
moAttack.setGeli(geli);
moAttack.cityGateAsk(); 3、 接口注入 :效果和属性注入无本质区别
通过容器完成依赖关系的注入
<?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.xsd">
<!--实现类实例化-->
<bean id="geli" class="com.smart.IoC.LiDeHua"/>
<bean id="MoAttack" class="com.smart.IoC.MoAttack"
p:geli-ref="geli">
</bean><!--通过geli-ref建立依赖关系-->
</beans>Java基础:
Java允许通过程序化的方式间接对Class进行操作。Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获知Class的结构信息,如构造函数、属性、方法。
public class ReflectTest {
public static Car initByDefaultConst() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//①通过类装载器获取Car对象
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Class clazz = classLoader.loadClass("com.smart.reflect.Car");
//②获取类的默认构造器对象并通过它实例化Car
Constructor constructor = clazz.getDeclaredConstructor((Class[]) null);
Car car = (Car) constructor.newInstance();
//③通过反射方法设置属性
Method setBrand = clazz.getMethod("setBrand",String.class);
setBrand.invoke(car,"红旗轿车");
Method setColor = clazz.getMethod("setColor",String.class);
setColor.invoke(car,"黑色");
Method setMaxSpeed = clazz.getMethod("setMaxSpeed",Integer.class);
123f2
setMaxSpeed.invoke(car,"黑色");
return car;
}
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Car car = initByDefaultConst();
car.introduce();
}
}该例中使用的反射类:ClassLoader、Class、 Constructor、Method
类装载器ClassLoader:通过寻找类的字节码文件并构造出类在JVM内部表示对象的组件.装载工作由其子类完成。
类件被装载解析后,在JVM内拥有一个对应的java.lang.Class类述对象,该类的实例都指向这个描述对象的引用,而类描述对象又拥有指向关联ClassLoader的引用。
Java反射机制:Class反射对象描述类语义结构,可以从Class对象中获取构造函数、成员变量、方法等类元素的反射对象,并通过这些反射对象对目标类进行操作。Java的反射体系保证了可以通过程序化的方式访问目标类中的所有元素,(对于private和protected成员变量和方法,只要JVM的安全机制允许,也可以通过反射进行调用。)
BeanFactory(IoC容器)和ApplicationContext(应用上下文或Spring容器)
Bean工厂是Spring框架最核心的接口,他提供了高级IoC的配置机制,使管理不同类型的Java对象成为可能
应用上下文建立再BeanFactory基础之上,提供了更多面向应用的功能。
BeanFactory是Spring框架的基础设施,面向Spring本身;ApplicationContext面向使用Spring框架的开发者,几乎所有的应用场合都可以直接使用ApplicationContext而非底层的BeanFactory
BeanFactory的类体系结构
BeanFactory最主要的方法getBean()——从容器中返回特定名称的Bean
通过BeanFactory启动IoC容器的时候,并不会初始化配置文件中的Bean,初始化动作发生再第一个调用时。对于单实例的Bean来说BeanFactory会缓存Bean实例,所以第二次使用getBean()获取Bean时,将直接从IoC容器的缓存中获取Bean实例。
ApplicationContext的类体系结构(ApplicationContext由BeanFactory派生出来)
ApplicationContext主要实现类是ClassPathXmlApplicationContext(从类路径下加载)和FileSystemXmlApplicationContext(从系统路径下加载)
ApplicationContext和BeanFactory初始化区别:BeanFactory初始化容器时并未实例化Bean,直到第一次访问某个Bean时才实例化目标Bean;ApplicationContext则在初始化应用上下文时就实例化所有单实例的Bean。
WebApplicationContext类体系结构:专门为web应用准备的,允许从相对于Web根目录的路径中装配配置文件完成初始化工作.
WebApplicationContext的初始化和ApplicationContext、BeanFactory有所区别,因为WebApplicationContext需要ServletContext实例,也就是必须在拥有web容器的前提下才能完成启动工作。(在web.xml中配置自启动的Servlet或定义web容器监听器)
Bean的生命周期
BeanFactory中Bean的生命周期图解
1)通过getBean()请求一个Bean时,如果容器注册了InstantiationAwareBeanPostProcessor 接口,则在Bean实例化之前调用接口的postProcessBeforeInstantiation()方法。
2)实例化Bean,如果容器注册了InstantiationAwareBeanPostProcessor 接口,Bean实例化之后,调用postProcessAfterInstantiation()方法。
3)如果Bean配置了属性信息,容器将配置值设置到Bean对应的属性中。在设置之前先调用InstantiationAwareBeanPostProcessor接口的postProcessPropertyValues()方法。
4)设置Bean的属性,
如果实现了BeanNameAware接口,则调用setBeanName()方法,将配置文件中该Bean的名称设置Bean中。
如果实现了BeanFactoryAware接口,则调用setBeanFactory()方法,将BeanFactory容器实例设置Bean中。
5)如果BeanFactory装配了BeanPostProcessor 后处理器,则将调用Object postProcessBeforeInstantiation(Object bean,String beanName)接口方法对Bean进行加工。
6)如果Bean实现了InitializingBean接口,则将调用接口的afterPropertiesSet()方法
7)如果<bean>中通过init-method属性定义了初始化方法,则将执行这个方法。
8)BeanPostProcessor后处理器定义了两个方法:①postProcessBeforeInstantiation()在 5)处调用;②Object postProcessBeforeInstantiation(),该方法调用时,容器再次获得对Bean进行加工处理的机会。
9)如果<bean>中指定Bean的范围为scope="protoType",则Bean返回给调用者,调用者负责Bean后续生命管理,Spring不再管理;若范围为scope="singleton",则将Bean放入Spring IoC容器的缓存池里,并将Bean的引用返回给调用者,Spring继续对这些Bean进行后续的生命管理。
10)对于scope="singleton"的情况,当容器关闭时,将触发对Bean后续生命周期的管理工作。如果Bean实现了DisposableBean接口,将调用Bean的destroy()方法。
11)对于scope="singleton"的Bean,如果通过<bean>的destroy-method属性指定了Bean的销毁方法,那么Spring将执行这个方法完成Bean资源的释放。
Bean的完整生命周期从Spring容器着手实例化Bean开始,直到最终销毁Bean。其中经历的关键点大致分为四类:
Bean自身的方法:如Bean调用构造函数实例化Bean、调用Setter设置Bean的属性值以及通过<bean>的init-method和destroy-method所指定的方法。
Bean级生命周期接口方法:BeanNameAware、BeanFacotyAware、InitializingBean和DisposableBean,这些接口方法由Bean直接实现。
容器级生命周期接口方法:图中带有
的步骤是由InstantiationAwareBeanPostProcessor和BeanPostProcessor两个接口实现的。称为实现类“后处理器”
工厂后处理器接口方法: 包括AspectJWeavingEnabler、CustomAutowireConfigurer、ConfigurationClassPostProcessor等方法,工厂后处理器也是容级的,在应用上下文装配配置文件后立即调用。
实例:
实现各种生命周期控制的Car
package com.smart.beanLifeCycle;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
/**
* @author chenpeng
* @date 2018/3/1 12:56
*/
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 void setBrand(String brand){
System.out.println("调用setBrand设置属性。");
this.brand = brand;
}
public void introduce(){
System.out.println("brand: "+brand+",color: "+color+",maxSpeed: "+maxSpeed);
}
/**
* BeanFactoryAware接口方法
* @param beanFactory
* @throws BeansException
*/
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("调用BeanFactoryAware.setBeanFactory()方法");
this.beanFactory = beanFactory;
}
/**
* BeanNameAware接口方法
* @param beanName
*/
public void setBeanName(String beanName) {
System.out.println("调用BeanNameAware.setBeanName()方法");
this.beanName = beanName;
}
/**
* InitializingBean接口方法
* @throws Exception
*/
public void destroy() throws Exception {
System.out.println("调用InitializingBean.afterPropertiesSet()方法");
}
/**
* DisposableBean接口方法
* @throws Exception
*/
public void afterPropertiesSet() throws Exception {
System.out.println("调用DisposableBean.destroy()方法");
}
/**
* 通过<bean>的init-method属性指定初始化方法
*/
public void myInit(){
System.out.println("调用init-method所指定的myInit(),将maxSpeed设置为240");
this.maxSpeed = 240;
}
/**
* 通过<bean>的destroy-method属性指定销毁方法
*/
public void myDestroy(){
System.out.println("调用destroy-method所指定的myDestroy()方法");
}
}
Car类分别实现了BeanFactoryAware,BeanNameAware,InitializingBean,DisposableBean这些Bean级的生命周期控制接口。
InstantiationAwareBeanPostProcessor实现类:
package com.smart.beanLifeCycle;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import java.beans.PropertyDescriptor;
/**
* @author chenpeng
* @date 2018/3/1 13:22
*/
public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter{
/**
*在实例化Bean前调用
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
//return super.postProcessBeforeInitialization(bean, beanName);
//对容器中的Car Bean进行处理
if("car".equals(beanName)){
System.out.println("InstantiationAware BeanPostProcessor. postProcessBeforeInstantiation");
}
return null;
}
/**
* 在实例化Bean后调用
*/
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
//return super.postProcessAfterInstantiation(bean, beanName);
//对容器中的Car Bean进行处理
if("car".equals(beanName)){
System.out.println("InstantiationAware BeanPostProcessor. postProcessAfterInstantiation");
}
return true;
}
/**
*在设置某个属性时调用
*/
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
//return super.postProcessPropertyValues(pvs, pds, bean, beanName);
//对容器中的Car Bean进行处理,还可以通过pdst入参进行过滤
if("car".equals(beanName)){
System.out.println("InstantiationAwareBeanPostProcessor. postProcessPropertyValues");
}
return pvs;
}
}
BeanPostProcessor实现类:
package com.smart.beanLifeCycle;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
* @author chenpeng
* @date 2018/3/1 13:40
*/
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("调用BeanPostProcessor.postProcessBeforeInitialization()," +
"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("调用BeanPostProcessor.postProcessAfterInitialization()," +
"将maxSpeed调整为200");
car.setMaxSpeed(200);
}
}
return bean;
}
}
beanLifeCycle.xml:配置Car
<?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.xsd"> <bean id="car" class="com.smart.beanLifeCycle.Car"
init-method="myInit"
destroy-method="myDestroy"
p:brand="红旗"
p:maxSpeed="200"/>
</beans>运行报错:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'car' defined in class path resource [beanLifeCycle.xml]: Invocation of init method failed; nested exception is java.lang.NullPointerException
发现书上代码有问题:
InstantiationAwareBeanPostProcessor接口注册返回对应的bean,不然报空,容器获取不到!
正确运行:
ApplicationContext中Bean的生命周期
Bean在应用上下文中的生命周期和在BeanFactory中的生命周期类似,不同的是:①如果Bean实现了ApplicationContextAware接口,会增加一个调用该接口的方法,setApplicationContext();②ApplicationContext可以利用Java反射机制自动识别出配置文件中定义的BeanPostProcessor、InitializationAwareBeanPostProcessor和BeanFactoryPostProcessor,并自动注册到应用上下文中,而BeanFactory则需要手动调用addBeanPostProcessor()方法进行注册。(开发中常使用ApplicationContext)
Bean的生命周期不但和其实现的接口有关还和Bean的作用范围有关。为了让Bean绑定在Spring框架上,推荐使用配置的方式而非接口的方式进行Bean的生命周期的控制。
相关文章推荐
- 精通Spring 4.x企业应用开发实战——IoC(四)
- 精通Spring 4.x企业应用开发实战——IoC(五)
- 《精通Spring 4.X企业应用开发实战》读书笔记1-1(IoC容器和Bean)
- 精通Spring 4.x企业应用开发实战——AOP(七①)
- Spring基础(精通Spring+4.x++企业应用开发实战 第7章)
- 精通Spring 4.x企业应用开发实战——高级主题(六)
- Spring的事务管理难点剖析(精通Spring+4.x++企业应用开发实战 第12章)
- Ioc容器 (精通Spring+4.x++企业应用开发实战 三)
- Spring容器高级主题(精通Spring+4.x++企业应用开发实战 五)
- 精通Spring 4.x企业应用开发实战——AOP(七②)
- Spring 入门实例 简易登录系统(精通Spring+4.x++企业应用开发实战 学习笔记一)
- Spring boot入门实例 简易登录(精通Spring+4.x++企业应用开发实战 学习笔记二)
- 精通Spring 4.x企业应用开发实战——笔记(一)
- 精通Spring 4.x企业应用开发实战——笔记(二)
- 在IoC容器中装配Bean(精通Spring+4.x++企业应用开发实战 四)
- Spring对DAO的支持(精通Spring+4.x++企业应用开发实战 第十章)
- Spring SpEL(精通Spring+4.x++企业应用开发实战 第九章)
- 学习《spring 3.x企业应用开发实战》之IOC容器概述
- 《Spring 3.x 企业应用开发实战》学习笔记 第三章 IoC容器概述 3.2 相关Java基础知识 类装载器 反射机制
- 《Spring 3.x 企业应用开发实战》学习笔记 第三章 IoC容器概述 3.2 相关Java基础知识 类装载器 反射机制