目录
1、使用 JDK 代理
使用 JDK 代理完成上一章 静态代理的事务管理的功能。
沿用上一章的几个类:
- 实体类:User
- 接口:UserService
- 接口实现类: UserServiceImpl
编写JDK 工厂代理类:
package com.lcy.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 基于 JDK 的动态代理工厂
*/
public class ProxyFactory implements InvocationHandler {
// 1 持有一个目标对象(被代理对象)
private Object target;
public ProxyFactory(){}
// 2 注入目标对象
public ProxyFactory(Object target){
this.target = target;
}
// 3 生成代理对象,使用的是反射技术
public <T> T getProxy() {
return (T)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
// 4 代理对象执行的方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("使用JDK动态代理----开启事务");
// 5 调用 目标对象的执行方法
Object result = method.invoke(target, args);
System.out.println("使用JDK动态代理----提交事务");
return result;
}
}
测试方法:
package com.lcy.test;
import com.lcy.model.User;
import com.lcy.proxy.ProxyFactory;
import com.lcy.service.UserService;
import com.lcy.service.impl.UserServiceImpl;
public class ProxyFactoryTest {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
ProxyFactory proxy = new ProxyFactory(userService);
UserService userServiceProxy = (UserService)proxy.getProxy();
userServiceProxy.save(new User(3, "张无忌"));
}
}
程序运行结果:
2、静态代理与JDK代理对比
静态代理:
1、必须实现目标对象接口。如果有多个对象需要代理(相同功能),那就需要给每个对象都定义多个代理的类。比如说 UserService -> UserServiceImplProxy ,DeptService -> DeptServiceImplProxy
UserServiceImplProxy 、DeptServiceImplProxy 这些代理类做的事情都一样,都是开启事务和提交事务。这样会导致系统中会有很多功能一样的代理类
2、一旦目标对象接口发生改变,静态代理的代理类也要跟着修改。比如说 UserService 接口中新增了remove 方法,在 UserServiceImplProxy 代理类中也要现在 remove 方法
JDK 代理:
1、不需要实现目标接口。可以为任意类进行代理。比如说:为 UserService 接口代理,只需要在创建代理类的时候,注入 UserService 接口的实现。然后利用 java反射技术动态生成代理类对象。
2、一旦目标对象接口发生改变,动态代理的代理类无需修改。比如说: UserService 接口新增了 remove 方法,ProxyFactory 代理工厂无需修改。