JDK动态代理API分析:(必须要求真实对象是有接口)
1.java.lang.reflect.Proxy类:java动态代理机制生成的所有动态代理类的父类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象.
1)主要方法:
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler handler)
2)方法职责:为指定类加载器、一组接口及处理器生成动态代理类实例
3)参数:
loader:类加载器,一般传递真实对象的类加载器
intrefaces:代理类需要实现的接口
handler:代理对象如何做增强
4)返回:创建的代理对象
2、java.lang.reflect.InvocationHandler接口
public Object invoke(Object proxy,Method method,Object[] args)
方法职责:负责集中处理动态代理类上的所有方法调用
参数:
proxy:生成的代理对象
method:当前调用的真实方法对象
args:当前调用方法的实参
返回:真实方法的返回结果
JDK动态代理操作步骤:
1.实现InvocationHandler接口,创建自己增强代码的处理器
2.给Proxy类提供ClassLoader对象和代理接口类型数组,创建动态代理对象
3.在处理器中实现增强操作
实现代码:
1.xml配置
<bean id="employeeDAO" class="com.bigfong.dao.impl.EmployeeDAOImpl" />
<bean id="transactionManager" class="com.bigfong.tx.TransactionManager" />
<bean id="employeeService" class="com.bigfong.service.impl.EmployeeServiceImpl">
<property name="dao" ref="employeeDAO" />
</bean>
<!-- 配置一个事务增强的类 -->
<bean id="transactionManagerAdvice" class="com.bigfong.tx.TransactionManagerAdvice">
<property name="target" ref="employeeService"/>
<property name="txManager" ref="transactionManager"/>
</bean>
2.IEmployeeService接口类,EmployeeServiceImpl是对IEmployeeService的实现类
3.TransactionManager类
//模拟事务管理器:
public class TransactionManager {
public void begin() {
System.out.println("开启事务");
}
public void commit() {
System.out.println("提交事务");
}
public void rollback() {
System.out.println("回滚事务");
}
}
4.TransactionManagerAdvice事务的增强类
@SuppressWarnings("all")
//事务的增强操作
public class TransactionManagerAdvice implements java.lang.reflect.InvocationHandler {
private Object target;//真实对象(对谁做增强)
private TransactionManager txManager;//事务管理器(模拟)
public void setTxManager(TransactionManager txManager) {
this.txManager = txManager;
}
public void setTarget(Object target) {
this.target = target;
}
//创建一个代理对象
public <T> T getProxyObject() {
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), //类加载器,一般跟上真实对象的类加载器
target.getClass().getInterfaces(), //真实对象所实现的接口(JDK动态代理必须要求真实对象有接口)
this);//如何做事务增强的对象
}
//如何为真实对象的方法做增强的具体操作
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object ret = null;
txManager.begin();
try {
//---------------------------------------------------------------
ret = method.invoke(target, args);//调用真实对象的方法
//---------------------------------------------------------------
txManager.commit();
} catch (Exception e) {
e.printStackTrace();
txManager.rollback();
}
return ret;
}
}
5.调用
@Autowired
private TransactionManagerAdvice advice;
//代理对象:com.sun.proxy.$Proxy19
@Test
void testSave() throws Exception {
//获取代理对象
IEmployeeService proxy = advice.getProxyObject();
proxy.save(new Employee());
}
@Test
void testUpdate() throws Exception {
//获取代理对象
IEmployeeService proxy = advice.getProxyObject();
proxy.update(new Employee());
}
JDK代理总结:
1.java动态代理使用java.lang,reflect包中的Proxy类与InvocationHandler接口两个来完成
2.要使用JDK动态代理,委托必须要定义接口
3.JDK动态代理将会拦截所有public的方法(因为只能调用接口定义的方法),这样即使在接口中增加了新的方法,不用修改代码也会被拦截
4.动态代理的最小单位是类(类中的所有方法都会被处理),如果只想拦截一部分方法,可以在invoke方法中对要执行的方法名进行判断
下一篇:spring5整理:(六)CGLIB动态代理-模拟事务