1.使用生命定制方法的前提:在scope="singleton"(单例)的情况下使用的,因为多例的情况下容器无法追踪对象的生命历程(创建后就不管他了).
生命定制方法方法:1.使用xml的bean标签属性:init-method 将主调bean的普通方法赋予该标签,该方法就可以不经调用直接输出(就像构造函数一样,但是性质还是一个普通方法)
2.使用接口:InitializingBean接口并实现他的afterPropertiesSet()接口
生命定制方法是在bean实例注值之后才开始进行的,是一个可以在初始化初期插入一个方法(其实也是一个反射原理:对象2帮主要对象1调用普通方法,让主要属性省去了实例化和调用普通方法过程)
spring允许生命定制在两个地方插入方法:1.实例注值之后 2.销毁实例之前(对于2其实也是bean标签下的destroy-method属性 因为要使用抽象的applicationcontext调用该方法 然后调用它的registershutdownhook方法,不常用,在此略过)
2.bean后处理器
bean后处理器即在其它对象内部实现接口BeanPostProcessor接口并实现其postProcessBeforeInitialization和postProcessAfterInitialization方法,作用是可以添加或者修改主要对象的方法或者属性
2.1bean后处理器优势:可以在不接触主对象的情况下,添加或者修改其属性和方法,主要通过beanpostprocessor接口完成该功能.
3.接下来,我们做一下生命定制方法和bean后处理器,然后对比一下生命定制方法和bean后处理器.
客人需求1:我们要输出:林先生利用工具
ioc+xml配置
3.1主类
package test;
public class person {
private String name;
public person() {
System.out.println("person类正在初始化");
}
public void setName(String name) {
this.name = name;
}
public void usetools() {
System.out.println(name+"在利用工具");
}
}
配置
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
">
<bean id="person" class="test.person">
<property name="name" value="林先生"/>
</bean>
</beans>
运行类
package test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ac {
public static void main(String[] args) {
ApplicationContext ac=new ClassPathXmlApplicationContext("bean.xml");
person p=ac.getBean("person",person.class);
p.usetools();
}
}
4.客人需求:我要在 输出"林先生利用工具前,在制造工具"但是不要修改运行类(即无法调用普通方法),只修改主类而且不用构造函数
不使用构造函数达到构造函数输出效果的,就是生命定制方法
在主类中添加该普通方法:
private void initialbefore() {//private 修饰之下是无法被其他类所调用的,但是生命定制方法可以
System.out.println("林先生使用工具齐前,在制造工具");
}
在配置中增加<bean id="person" class="test.person" init-method="initialbefore">init-method方法(它就是生命定制的核心)
然后走运行类
5.客人又要求:林先生这个名字在利用工具之前就修改名字,而且不修改主类运行类任何内容(不给主类运行类任何污染)
不给主类任何污染:我们可以考虑使用bean后处理器 步骤:给出一个普通java类实现beanpostprocessor接口 实现下面...before...,....after....方法,在这两方法里引用主类对象调用主类属性修改方法即可以在不污染的情况下修改主类(说白了就是一个反射方法),最后在配置中添加bean id属性(在该简单例子中可以不写id因为又没有别的bean要调用它) class属性(除了抽象bean之外,其他bean都要写class的)
5.1实现了beanpostprocessor的普通java类
package test;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class beanpost implements BeanPostProcessor {
public Object postProcessAfterInitialization(Object bean, String beanname)
throws BeansException {
if(bean instanceof person){
person p=(person) bean;
p.setName("林思齐");
}
System.out.println("林先生已经修改名字--->"+beanname);
return bean;
}//貌似这是一个实例化工厂
public Object postProcessBeforeInitialization(Object bean, String beanname)
throws BeansException {
System.out.println("林先生需要改名字");
return bean;
}
}
配置上多些一个 <bean class="test.beanpost"/>
(多了一个类就多了一个bean,给ioc解析利用)
运行结果
总结:生命定制方法是定制一个方法,该方法会在ioc注值之后开始输出
bean后处理器显然比生命周期更为强大,他不仅可以在注入值之后为主类添加方法而且还可以修改属性
共同点:他们都利用了反射机制,在其他对象中对主要对象的方法进行修改或者增加,bean后处理器还可以对主要对象的属性进行修改或者注入.
他们的执行顺序
bean后处理器的 before 方法最先执行----->生命定制方法的接口式的afterpropertiesset方法-------->生命定制方法的init-method方法-------->bean后处理器的 after方法