4.BeanPostProcessor 後處理Bean
Bean種類
普通bean:之前操作的都是普通bean。<bean id="" class="A"> ,spring直接創建A實例,並返回
FactoryBean:是一個特殊的bean,具有工廠生成對象能力,只能生成特定的對象。
bean必須使用 FactoryBean接口,此接口提供方法 getObject() 用於獲得特定bean。
<bean id="" class="FB"> 先創建FB實例,使用調用getObject()方法,並返回方法的返回值
FB fb = new FB();
return fb.getObject();
l BeanFactory 和
BeanFactory:工廠,用於生成任意bean。
FactoryBean:特殊bean,用於生成另一個特定的bean。例如:ProxyFactoryBean ,此工廠bean用於生產代理。<bean id="" class="....ProxyFactoryBean"> 獲得代理對象實例。AOP使用
作用域
取值:
singleton 單例,默認值。
prototype 多例,每執行一次getBean將獲得一個實例。例如:struts整合spring,配置action多例。
配置信息
<bean id="" class="" scope="">
<bean id="userServiceId" class="com.itheima.d_scope.UserServiceImpl" scope="prototype" ></bean>
生命周期
初始化和銷毀
目標方法執行前後執行後,將進行初始化或銷毀。
<bean id="" class="" init-method="初始化方法名稱" destroy-method="銷毀的方法名稱">
1 spring配置
<!-- init-method 用於配置初始化方法,準備數據等 destroy-method 用於配置銷毀方法,清理資源等 --> <bean id="userServiceId" class="com.itheima.e_lifecycle.UserServiceImpl" init-method="myInit" destroy-method="myDestroy" ></bean>
2 測試
@Test public void demo02() throws Exception{ //spring 工廠 String xmlPath = "com/itheima/e_lifecycle/beans.xml"; ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); UserService userService = (UserService) applicationContext.getBean("userServiceId"); userService.addUser(); //要求:1.容器必須close,銷毀方法執行; 2.必須是單例的 // applicationContext.getClass().getMethod("close").invoke(applicationContext); // * 此方法接口中沒有定義,實現類提供 applicationContext.close(); }
BeanPostProcessor 後處理Bean
spring 提供一種機制,只要實現此接口BeanPostProcessor,並將實現類提供給spring容器,spring容器將自動執行,在初始化方法前執行before(),在初始化方法後執行after() 。 配置<bean class="">
l Factory hook(勾子) that allows for custom modification of new bean instances, e.g. checking for marker interfaces or wrapping them with proxies.
l spring提供工廠勾子,用於修改實例對象,可以生成代理對象,是AOP底層。
模擬
A a =new A();
a = B.before(a) --> 將a的實例對象傳遞給後處理bean,可以生成代理對象並返回。
a.init();
a = B.after(a);
a.addUser(); //生成代理對象,目的在目標方法前後執行(例如:開啟事務、提交事務)
a.destroy()
1.編寫實現類
MyBeanPostProcessor.java
package com.jd.lifecycle; 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; /** * @author weihu * @date 2018/8/12/012 23:15 */ public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object o, String s) throws BeansException { System.out.println("前方法:"+o); return o; } @Override public Object postProcessAfterInitialization(Object o, String s) throws BeansException { System.out.println("後方法:"+o); //o目標對象 //生成jdk代理 return Proxy.newProxyInstance(MyBeanPostProcessor.class.getClassLoader(), o.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("---開啟事物-----"); //執行目標方法 Object obj = method.invoke(o, args); System.out.println("-----提交事物-------"); return obj; } }); } }
UserService.java
package com.jd.lifecycle; public interface UserService { public void addUser(); }
UserServiceImpl.java
package com.jd.lifecycle; public class UserServiceImpl implements UserService { @Override public void addUser() { System.out.println("lifecycle add user"); } public void myInit(){ System.out.println("初始化"); } public void myDestroy(){ System.out.println("銷毀"); } }
beans.xml
<?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"> <!-- init-method 用於配置初始化方法,準備數據等 destroy-method 用於配置銷毀方法,清理資源等 --> <bean id="userServiceId" class="com.jd.lifecycle.UserServiceImpl" init-method="myInit" destroy-method="myDestroy"></bean> <!--將後處理的實現類註冊給spring--> <bean class="com.jd.lifecycle.MyBeanPostProcessor"></bean> </beans>
TestCycle.java
package com.jd.lifecycle; import org.junit.Test; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author weihu * @date 2018/8/12/012 23:24 */ public class TestCycle { @Test public void testProx(){ String xmlPath="com/jd/lifecycle/beans.xml"; ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); UserService userService = (UserService) applicationContext.getBean("userServiceId"); userService.addUser(); //要求:1.容器必須close,銷毀方法執行; 2.必須是單例的 // applicationContext.getClass().getMethod("close").invoke(applicationContext); // * 此方法接口中沒有定義,實現類提供 applicationContext.close(); } }
4.BeanPostProcessor 後處理Bean