代理模式
一 代理模式简介
代理(Proxy)是一种设计模式 提供了对目标对象另外的访问方式
代理对象代理目标对象 达到增强目标对象功能的目的
二 静态代理
需要定义接口或者父类 代理对象与目标对象一起实现相同接口或者继承相同父类
优点: 在不修改目标对象的功能前提下 对目标功能扩展
缺点: 因为代理对象需要与目标对象一起实现相同接口或者继承相同父类 所以会有很多代理类 导致类太多 同时 如果接口增加方法 代理对象与目标对象都要维护
1. 接口
/** * 接口 * Created by Hy on 2020/7/10. */ public interface IUserService { void insertUser(); String deleteUser(int id); }
2. 目标对象
/** * 目标对象 * Created by Hy on 2020/7/10. */ public class UserService implements IUserService { @Override public void insertUser() { System.out.println("insert ok"); } @Override public String deleteUser(int id) { System.out.println("delete... ... ..."); return "id = " + id + " delete ok"; } }
3. 代理对象
/** * 代理对象 * Created by Hy on 2020/7/13. */ public class UserServiceProxy implements IUserService { private IUserService target; //目标对象 public UserServiceProxy(IUserService target) { this.target = target; } @Override public void insertUser() { System.out.println("增强方法体 1/2"); target.insertUser(); System.out.println("增强方法体 2/2"); } @Override public String deleteUser(int id) { id++; //增强参数 String s = target.deleteUser(id); s = s + "!!!"; //增强返回值 return s; } }
4. 测试
@Test public void test01() { // 创建目标对象 UserService target = new UserService(); // 创建代理对象 UserServiceProxy proxy = new UserServiceProxy(target); // 使用代理对象调用方法 proxy.insertUser(); String s = proxy.deleteUser(1); System.out.println(s); }
三 动态代理(接口代理)
需要定义接口让目标对象实现 使用java.lang.reflect.Proxy动态的在内存中构建代理对象
优点: 在不修改目标对象的功能前提下 对目标功能扩展 代理对象不需要实现接口
缺点: 目标对象一定要实现接口 否则不能用动态代理
1. 接口
/** * 接口 * Created by Hy on 2020/7/10. */ public interface IUserService { void insertUser(); String deleteUser(int id); }
2. 目标对象
/** * 目标对象 * Created by Hy on 2020/7/10. */ public class UserService implements IUserService { @Override public void insertUser() { System.out.println("insert ok"); } @Override public String deleteUser(int id) { System.out.println("delete... ... ..."); return "id = " + id + " delete ok"; } }
3. 代理工厂
/** * 代理工厂 * Created by Hy on 2020/7/13. */ public class ProxyFactory { private Object target; //目标对象 public ProxyFactory(Object target) { this.target = target; } public Object createProxyInstance() { return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { /** * 代理对象调用的所有方法都会触发该方法执行 * @param proxy 代理对象 * @param method 被代理的方法 * @param args 被代理的方法传参 * @return 被代理的方法返回值 * @throws Throwable 异常 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if ("deleteUser".equals(method.getName())) { // 增强指定方法 int id = (int) args[0]; id++; //增强参数 System.out.println("增强方法体 1/2"); String invoke = (String) method.invoke(target, id); invoke = invoke + "!!!"; //增强返回值 System.out.println("增强方法体 2/2"); return invoke; } else { // 其它方法默认实现 Object invoke = method.invoke(target, args); return invoke; } } }); } }
4. 测试
@Test public void test01() { // 创建目标对象 UserService target = new UserService(); System.out.println(target.getClass()); // 创建代理对象 IUserService proxy = (IUserService) new ProxyFactory(target).createProxyInstance(); System.out.println(proxy.getClass()); // 使用代理对象调用方法 proxy.insertUser(); String s = proxy.deleteUser(1); System.out.println(s); }
四 CGLIB代理(子类代理)
通过在内存中构建一个子类对象从而实现对目标对象功能的扩展 CGLIB是一个强大的高性能的代码生成包 底层使用一个小而快的字节码处理框架ASM来转换字节码并生成新的类
优点: 在不修改目标对象的功能前提下 对目标功能扩展 代理对象与目标对象都不需要实现接口
缺点: 需要引入CGLIB的JAR文件
1. 目标对象
/** * 目标对象 * Created by Hy on 2020/7/10. */ public class UserService { public void insertUser() { System.out.println("insert ok"); } public String deleteUser(int id) { System.out.println("delete... ... ..."); return "id = " + id + " delete ok"; } }
2. 代理工厂
/** * 代理工厂 * Created by Hy on 2020/7/13. */ public class ProxyFactory { private Object target; //目标对象 public ProxyFactory(Object target) { this.target = target; } public Object createProxyInstance() { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(target.getClass()); enhancer.setCallback(new MethodInterceptor() { /** * 代理对象调用的所有方法都会触发该方法执行 * @param proxy 代理对象 * @param method 被代理的方法 * @param args 被代理的方法传参 * @param methodProxy 代理的方法 * @return 被代理的方法返回值 * @throws Throwable 异常 */ @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { if ("deleteUser".equals(method.getName())) { // 增强指定方法 int id = (int) args[0]; id++; //增强参数 System.out.println("增强方法体 1/2"); String invoke = (String) method.invoke(target, id); invoke = invoke + "!!!"; //增强返回值 System.out.println("增强方法体 2/2"); return invoke; } else { // 其它方法默认实现 Object invoke = methodProxy.invokeSuper(proxy, args); //等同 method.invoke(target, args); return invoke; } } }); return enhancer.create(); } }
3. 测试
@Test public void test01() { // 创建目标对象 UserService target = new UserService(); System.out.println(target.getClass()); // 创建代理对象 UserService proxy = (UserService) new ProxyFactory(target).createProxyInstance(); System.out.println(proxy.getClass()); // 使用代理对象调用方法 proxy.insertUser(); String s = proxy.deleteUser(1); System.out.println(s); }