4.spriing:Bean的生命周期/工厂方法配置Bean/FactoryBean
1.Bean的生命周期
scope:singleton/prototype
1)spring容器管理singleton作用的生命周期,spring能够精确知道Bean合适创建,何时初始化完成,以及何时被销毁
2)spring容器管理prototype作用的生命周期,spring只负责创建,容器实例化之后就交给客户端进行管理,spring容器不会再
跟踪其生命周期。
可以借鉴servlet的生命周期“实例化--初始化--接受请求--销毁”
Spring IOC容器可以管理Bean的生命周期,Spring允许在Bean生命周期的特定点执行特定的任务
在SpringIOC容器对Bean的生命周期进行管理的过程
->通过构造器或者工厂的方法创建Bean实例
->为Bean的属性设置值和其他的Bean的引用
->调用bean的初始化方法
->bea调用使用了
->当容器关闭的时候,调用Bean的销毁方法
在Bean的声明里设置 ini-method 和 destroy-method属性,为Bean指定初始化和销毁的方法
Car.java
public class Car { private String brand;public void init() { System.out.println("init"); }public void destroy() { System.out.println("destroy"); }
、
public void setBrand(String brand) {
System.out.println("setBrand");
this.brand = brand;
}
//....
}
applicationContext.xml
<bean id="car" class="com.MrChengs8.TheLifeCycle.Car" init-method="init"
destroy-method="destroy"> <property name="brand" value="Aodi"></property>
</bean>
测试:
Car car = (Car) ctx.getBean("car"); System.out.println(car); //关闭IOc容器 //ClassPathXmlApplicationContext //子接口里面有关闭IOC容器的方法 ctx.close();
setBrand
init Car [brand=Aodi] destroy
先调用构造函数和设置属性,然后再init()
Bean的后置处理器:
创建Bean后置处理器:
Bean后置处理器允许在调用初始化的时候对前后的Bean进行额外的处理
Bean的后置处理器对IOC容器里的所有的Bean实例逐一处理,而非单一的实例,
其典型的应用是:检查Bean属性的正确性或者根据特定的标准去修改bean
对Bean后置处理器而言,更需要实现的是Interface BeanPostProcessor接口,在初始化方法被调用的前后,
Spring将把每个Bean的实例分别传递给接口以下的两个方法
->postProcessAfterInitialization(Object arg0, String arg1)
->postProcessBeforeInitialization(Object arg0, String arg1)
实现并提供两个方法的实现在类中
Object arg0, String arg1
arg0:bean的实例本身
arg1:IOC容器配置的bean的名字
在IOC容器会自动识别是一个后置处理器
TheLatterPostprocessor.java
public class TheLatterPostprocessor implements BeanPostProcessor{ @Override public Object postProcessAfterInitialization(Object bean, String arg1) throws BeansException { System.out.println("postProcessAfterInitialization__After__::" + arg1 + "---" + bean); Car car = new Car(); car.setBrand("BBBBB"); return car; } @Override public Object postProcessBeforeInitialization(Object bean, String arg1) throws BeansException { System.out.println("postProcessBeforeInitialization__Before__::" + arg1 + "---" + bean); return bean; } }
applicationContext.xml
<!--配置Bean的后置处理器 -->
<bean class="com.MrChengs8.TheLifeCycle.TheLatterPostprocessor"></bean>
setBrand postProcessBeforeInitialization__Before__::car---Car [brand=Aodi] init postProcessAfterInitialization__After__::car---Car [brand=Aodi] setBrand Car [brand=BBBBB] destroy
2.工厂方法配置Bean
1).实例工厂实例化
实例工厂方法:将对象创建的过程封装到另外一个对象实例方法里,当客户需要请求对象时,只需要简单的调用该实例方法发,不必关心创建的细节
要声明通过实例工厂方法创建Bean:
->在bean的factory-method属性里指定拥有该方法的Bean
->在factory-method属性里指定该工厂方法的名称
->使用 construtor元素为工厂方法传递参数
Car.java
public class Car { private String brand; private double price;public Car(String brand, double price) { super(); this.brand = brand; this.price = price; } //..... }
InstanceFactoryMethod.java
public class InstanceFactoryMethod { private Map<String, Car> cars = null; public InstanceFactoryMethod(){ cars = new HashMap<String, Car>(); cars.put("aodi", new Car("aodi", 10000)); cars.put("ford", new Car("ford",20000)); } public Car getCar(String name){ return cars.get(name); } }
applicationContext.xml
<!-- 配置工厂的实例 --> <bean id="car1" class="com.MrChengs9.FactoryMethod.InstanceFactoryMethod" ></bean> <!-- 通过实例工厂方法来配置bean --> <bean id="car2" factory-bean="car1" factory-method="getCar"> <constructor-arg value="ford"></constructor-arg> </bean>
测试
Car car2 = (Car) ctx.getBean("car2"); System.out.println(car2);
Car [brand=ford, price=20000.0]
2).静态工厂方法
利用静态工厂方法可以把bean注入到IOC容器中。在XML文件中配置bean时,要指定class的属性为工厂的类;factory-method属性指定工厂类中
工厂方法,用于创建bean;constrctor-arg用于给工厂方法传递参数
StaticFactoryMethod.java
public class StaticFactoryMethod { private static Map<String, Car> cars = new HashMap<String, Car>(); static{ cars.put("audi", new Car("audi", 1234)); cars.put("ford", new Car("ford", 4321)); } public static Car getCars(String name){ return cars.get(name); } }
applicationContext.xml
<!-- 静态工厂方法来配置Bean实例,不是配置静态工厂方法实例,而是去配置Bean实例 --> <!-- Class属性指向静态工厂方法的全类名 factory-method:指向静态工厂的名字 constructor-arg:工厂需要传入canshu,则使用此元素 --> <bean id="car" class="com.MrChengs9.FactoryMethod.StaticFactoryMethod" factory-method="getCars"> <constructor-arg value="audi"></constructor-arg> </bean>
Car car1 = (Car) ctx.getBean("car"); System.out.println(car1);
Car [brand=audi, price=1234.0]
3.FactoryBean
FactoryBean是一个接口,要用的话就要实现它。他有三个方法:
getObject() //返回bean对象
getObjectType() //返回bean的类型
isSingleton() //是否单例
CarFactoryBean.java
public class CarFactoryBean implements FactoryBean<Car>{ private String brand; public void setBrand(String brand) { this.brand = brand; } //返回bean的对象 @Override public Car getObject() throws Exception { // TODO Auto-generated method stub return new Car(brand,100000); } //返回bean的类型 @Override public Class<?> getObjectType() { // TODO Auto-generated method stub return Car.class; } //返回bean是不是单实例的 @Override public boolean isSingleton() { // TODO Auto-generated method stub return false; } }
Car.java
public class Car { private String brand; private double price;public Car(String brand, double price) { super(); this.brand = brand; this.price = price; }
//...... }
applicationContext.xml
通过FactoryBean来配置Bean的实例
class:指向FactoryBean的全类名
property:配置FactoryBean的属性
但是实际返回的是FactoryBean的getObject()方法
<bean id="car" class="com.MrChengsa.FactoryBean.CarFactoryBean"> <property name="brand" value="BMW"></property> </bean>
Car car = (Car) ctx.getBean("car"); System.out.println(car);
Car [brand=BMW, price=100000.0]
但实际返回实例确是 FactoryBean 的 getObject() 方法返回的实例!