一.分析(必須要求真實對象是有接口的)
1. java.lang.reflext.proxy 類:java 動態(tài)代理機(jī)制生成的所有動態(tài)代理類的父類,它提供了一組靜態(tài)方法為一組接口動態(tài)地生成代理類及其對象
主要方法:public static Object newProxyInstance(ClassLoader loader, Class<?>[]interface, invocationHander hander)
方法職責(zé):為指定類加載器,一組接口及調(diào)用處理器生成動態(tài)代理實例
參數(shù)
loader :類加載器,一般傳遞真實對象的加載器
interface :代理類需要實現(xiàn)的接口
hander:代理對象如何做增強(qiáng)
返回:創(chuàng)建的代理對象
2.java.lang.reflect.invocationHander接口:
public invoke(Object proxy, Method method,Object[] args)
方法職責(zé):負(fù)責(zé)集中處理動態(tài)代理類上的所有方法調(diào)用
參數(shù):
proxy:生成代理對象
methos:當(dāng)前調(diào)用的真實方法對象
args:當(dāng)前調(diào)用方法的實參
返回:真實方法的返回結(jié)果n
二.JDK 動態(tài)代理操作步驟:
1.創(chuàng)建一個代理對象
2.實現(xiàn)invocationHander接口
3.覆蓋invoke(),為真實對象方法做增強(qiáng)的具體操作
代碼演示:
package com.keen.proxy.tx;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
@SuppressWarnings("all")//忽略所有警告
public class TransactionManagerAdvice implements InvocationHandler{
private Object targer;//真實對象,即對誰做增強(qiáng)
private TransactionManager txManager;//事務(wù)管理器(模擬)
public void setTarger(Object targer) {
this.targer = targer;
}
public void setTxManager(TransactionManager txManager) {
this.txManager = txManager;
}
//創(chuàng)建一個代理對象
public <T> T getproxyObject() {
return (T) Proxy.newProxyInstance(targer.getClass().getClassLoader(),//loader類加載器,一般跟上真實對象的類加載器
targer.getClass().getInterfaces(),//真實對象所實現(xiàn)的接口(jdk動態(tài)代理必須要求真實對象有接口)
this);//如何做事務(wù)增強(qiáng)的對象因為繼承了InvocationHandler,所以直接用this就可以了
}
@Override
//如何為真實對象的方法增強(qiáng)的具體操作
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object ret = null;
txManager.begin();
//調(diào)用真實對象的方法
try {
ret = method.invoke(targer, args);//調(diào)用對象真實的方法
txManager.commit();
} catch (Exception e) {
e.printStackTrace();
txManager.rollback();
}
return ret;
}
}
context.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"
xmlns:context="http://www.springframework.org/schema/context"
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-4.3.xsd">
<!-- di注解解析器 -->
<!-- <context:annotation-config/> -->
<!--IOC注解解析器 -->
<!-- <context:component-scan base-package="com.keen.proxy"/> -->
<bean id = "employeeDAO" class = "com.keen.proxy.dao.EmployeeDAOimpl"/>
<!-- 事務(wù)管理器 -->
<bean id = "transactionManager" class = "com.keen.proxy.tx.TransactionManager"/>
<!-- 配置事務(wù)增強(qiáng)類 -->
<bean id = "transactionManagerAdvice" class = "com.keen.proxy.tx.TransactionManagerAdvice" >
<property name="txManager" ref ="transactionManager"/>
<property name="targer" >
<!-- 把employeeService作為內(nèi)部bean -->
<bean class ="com.keen.proxy.service.IEmployeeServiceImpl">
<property name = "dao" ref = "employeeDAO"/>
</bean>
</property>
</bean>
</beans>
測試類
package com.keen.proxy;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import com.keen.proxy.domain.Employee;
import com.keen.proxy.service.IEmployeeService;
import com.keen.proxy.tx.TransactionManagerAdvice;
@SpringJUnitConfig
public class AutoTest {
@Autowired
private TransactionManagerAdvice advice;
@Test
void testSave() throws Exception {
//獲取代理對象 class com.sun.proxy.$Proxy19
IEmployeeService service = advice.getproxyObject();
service.save(new Employee());
}
@Test
void testUpdate() throws Exception {
IEmployeeService service = advice.getproxyObject();
service.update(new Employee());
}
}
??:其他涉及相關(guān)的類和上一篇靜態(tài)代理的類一樣的,只是動態(tài)代理不需要靜態(tài)代理那個IEmployeeServiceProxy類了。我們用TransactionManagerAdvice 替代了。