Java中的三种代理模式
2018-12-05 本文已影响13人
哪吒小子
- 我的技术博客:https://nezha.github.io,https://nezhaxiaozi.coding.me
- 我的简书地址:https://www.jianshu.com/u/a5153fbb0434
第一种:静态代理
程序实现
代码实现
1.设计接口
public interface IUserDao {
void save();
}
2.实现接口
public class UserDao implements IUserDao {
@Override
public void save() {
System.out.println("----已经保存数据!----");
}
}
3.代理类
必须实现接口
public class UserDaoProxy implements IUserDao {
//接收保存目标对象
private IUserDao target;
public UserDaoProxy(IUserDao target){
this.target=target;
}
@Override
public void save() {
System.out.println("开始事务...");
target.save();//执行目标对象的方法
System.out.println("提交事务...");
}
}
4.测试类
public class App {
public static void main(String[] args) {
//目标对象
UserDao target = new UserDao();
//代理对象,把目标对象传给代理对象,建立代理关系
UserDaoProxy proxy = new UserDaoProxy(target);
proxy.save();//执行的是代理的方法
}
}
第二种:JDK动态代理
代码实现
1.设计接口
public interface IUserDao {
void save();
}
2.实现接口
public class UserDao implements IUserDao {
@Override
public void save() {
System.out.println("----已经保存数据!----");
}
}
3.代理类
不需要实现接口
public class ProxyFactory {
//维护一个目标对象
private Object target;
public ProxyFactory(Object target){
this.target=target;
}
//这是Java8语法
public Object getProxyInstanceLambda(){
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
(proxy,method,args) -> {
System.out.println("开始事务2");
//执行目标对象方法
Object returnValue = method.invoke(target, args);
System.out.println("提交事务2");
return returnValue;
});
}
//传统语法
public Object getProxyInstance(){
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开始事务2");
//执行目标对象方法
Object returnValue = method.invoke(target, args);
System.out.println("提交事务2");
return returnValue;
}
});
}
}
4.测试类
public class App {
public static void main(String[] args) {
// 目标对象
IUserDao target = new UserDao();
// 【原始的类型 class UserDao】
System.out.println(target.getClass());
// 给目标对象,创建代理对象
IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstanceLambda();
// class $Proxy0 内存中动态生成的代理对象
System.out.println(proxy.getClass());
// 执行方法 【代理对象】
proxy.save();
}
}
第三种:Cglib代理
代码实现
1.目标对象类
public class UserDao {
public void save() {
System.out.println("----已经保存数据!----");
}
}
2.Cglib代理工厂
public class ProxyFactory implements MethodInterceptor {
//维护目标对象
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
//给目标对象创建一个代理对象
public Object getProxyInstance(){
//1.工具类
Enhancer en = new Enhancer();
//2.设置父类
en.setSuperclass(target.getClass());
//3.设置回调函数
en.setCallback(this);
//4.创建子类(代理对象)
return en.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("开始事务...");
//执行目标对象的方法
Object returnValue = method.invoke(target, objects);
System.out.println("提交事务...");
return returnValue;
}
}
3.测试类
public class App {
public static void main(String[] args) {
//目标对象
UserDao target = new UserDao();
//代理对象
UserDao proxy = (UserDao)new ProxyFactory(target).getProxyInstance();
//执行代理对象的方法
proxy.save();
}
}
三者的区别
1.静态代理
目标对象要实现接口,而且代理对象需要实现接口。
这样的代理类只能代理特定接口的对象,灵活度不够。
2.JDK动态代理
代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理
3.CGLib动态代理
代理对象不需要实现接口,目标对象也可以是单纯的一个对象。
在Spring的AOP编程中:
如果加入容器的目标对象有实现接口,用JDK代理.
如果目标对象没有实现接口,用Cglib代理.
参考文献
详解 Java 中的三种代理模式:https://mp.weixin.qq.com/s/nBmbNP2mR7ei-lDsuOxjWg
你真的完全了解Java动态代理吗?看这篇就够了:https://mp.weixin.qq.com/s/P-nrfyyWfRUurKgF4dnugA