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調用銷毀方法 這是銷毀方法
Java Spring-Bean