Java Spring-Bean
2017-11-06 18:59:30
- Bean初始化和销毁方法
配置初始化和销毁的方法:
* init-method=”setup”
* destroy-method=”teardown”
执行销毁的时候,必须手动关闭工厂,而且只对scope=” singleton ”(也就是默认值)有效。
配置文件:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="bean" class="spring3.Bean" init-method="setup" destroy-method="teardown"> <property name="s" value="hello"/> </bean> </beans>
代码文件:
public class Bean { private String s; public void setS(String s) { this.s = s; } public void setup(){ System.out.println("这是初始化方法"); } public void teardown(){ System.out.println("这是销毁方法"); } } public class Spring3 { @Test public void demo1(){ ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("" + "config2.xml"); Bean b = (Bean) ac.getBean("bean"); // 只有ClassPathXmlApplicationContext有close()方法,ApplicationContext没有 ac.close(); } }
- Bean的生命周期
Bean的生命周期的11个步骤:
1.instantiate bean对象实例化
2.populate properties 封装属性
3.如果Bean实现BeanNameAware 执行 setBeanName(让当前类了解Spring容器)
4.如果Bean实现BeanFactoryAware 或者 ApplicationContextAware 设置工厂 setBeanFactory 或者上下文对象setApplicationContext(让当前类了解Spring容器)
5.如果存在类实现 BeanPostProcessor(前处理Bean) ,执行postProcessBeforeInitialization
6.如果Bean实现InitializingBean 执行 afterPropertiesSet
7.调用<bean init-method="init"> 指定初始化方法 init
8.如果存在类实现 BeanPostProcessor(后处理Bean) ,执行postProcessAfterInitialization
9.执行业务处理
10.如果Bean实现 DisposableBean 执行 destroy
11.调用<bean destroy-method="customerDestroy"> 指定销毁方法 customerDestroy
配置文件:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="bean" class="spring3.Bean" init-method="setup" destroy-method="teardown"> <property name="s" value="hello"/> </bean> <!--后处理bean不需要添加id,系统会自动调用--> <bean class="spring3.MyBeanPostProcessor"/> </beans>
代码文件:
public interface B { public void add(); } public class Bean implements B,DisposableBean,BeanNameAware,ApplicationContextAware,InitializingBean{ private String s; Bean(){ System.out.println("第一步:默认构造方法"); } public void setS(String s) { System.out.println("第二步:属性注入"); this.s = s; } public void add(){ System.out.println("第九步:处理业务逻辑"); System.out.println("这是添加方法"); } public void setup(){ System.out.println("第七步:这是初始化方法"); } public void teardown(){ System.out.println("这是销毁方法"); } @Override public void setBeanName(String s) { System.out.println("第三步:注入配置的id号"+s); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { System.out.println("第四步:注入ApplicationContext"+applicationContext); } @Override public void afterPropertiesSet() throws Exception { System.out.println("第六步:属性设置后执行"); } @Override public void destroy() throws Exception { System.out.println("第十步:Spring调用销毁方法"); } }
自定义的 BeanPostProcessor
public class MyBeanPostProcessor implements BeanPostProcessor { /** * bean:实例对象 * beanName:在配置文件中配置的类的标识. */ public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("第五步:初始化之前执行..."); return bean; } public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException { System.out.println("第八步:初始化后执行..."); return bean; } }
结果:
public void demo1(){ ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("" + "config2.xml"); Bean b = (Bean) ac.getBean("bean"); b.add(); // 只有ClassPathXmlApplicationContext有close()方法,ApplicationContext没有 ac.close(); } 输出: 第一步:默认构造方法 第二步:属性注入 第三步:注入配置的id号bean 第四步:注入ApplicationContextorg.springframework.context.support.ClassPathXmlApplicationContext@6591f517: startup date [Mon Nov 06 19:50:53 CST 2017]; root of context hierarchy 第五步:初始化之前执行... 第六步:属性设置后执行 第七步:这是初始化方法 第八步:初始化后执行... 第九步:处理业务逻辑 这是添加方法 第十步:Spring调用销毁方法 这是销毁方法
当然了在后处理Bean的时候是可以进行动态代理进行增强的。
但是要特别注意,这个时候在定义对象的时候,必须是使用接口来作为类型名,而不能是实现类,因为这次返回的是代理类,代理类和实现类是平级关系,是无法相互转换的。
import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class MyBeanPostProcessor implements BeanPostProcessor { /** * bean:实例对象 * beanName:在配置文件中配置的类的标识. */ public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("第五步:初始化之前执行..."); return bean; } public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException { System.out.println("第八步:初始化后执行..."); // 动态代理进行增强 Object proxy = Proxy.newProxyInstance(bean.getClass().getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("权限校验:"); Object res = method.invoke(bean, args); return res; } }); return proxy; } } public class Spring3 { @Test public void demo1(){ ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("" + "config2.xml"); B b = (B) ac.getBean("bean"); b.add(); // 只有ClassPathXmlApplicationContext有close()方法,ApplicationContext没有 ac.close(); } } 结果: 第一步:默认构造方法 第二步:属性注入 第三步:注入配置的id号bean 第四步:注入ApplicationContextorg.springframework.context.support.ClassPathXmlApplicationContext@6591f517: startup date [Mon Nov 06 20:18:39 CST 2017]; root of context hierarchy 第五步:初始化之前执行... 第六步:属性设置后执行 第七步:这是初始化方法 第八步:初始化后执行... 权限校验: 第九步:处理业务逻辑 这是添加方法 第十步:Spring调用销毁方法 这是销毁方法