代理模式是一种设计模式,提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。简言之,代理模式就是设置一个中间代理来控制访问原目标对象,以达到增强原对象的功能和简化访问方式。
这种代理方式需要代理对象和目标对象实现一样的接口。
优点:可以在不修改目标对象的前提下扩展目标对象的功能。
缺点:冗余。由于代理对象要实现与目标对象一致的接口,会产生过多的代理类。不易维护。一旦接口增加方法,目标对象与代理对象都要进行修改。
举例:明星代理
//定义代理类接口 public interface Star { /** * * 面谈 */ public void confer(); /** * 签合同 */ public void signContract(); /** * 订票 */ public void bookTicket(); /** * 唱歌 */ public void sing(); /** * 收钱 */ public void collectMoney(); }
//定义被代理目标对象实现Star接口 public class RealStar implements Star{ @Override public void confer() { System.out.println("明星面谈"); } @Override public void signContract() { System.out.println("明星签合同"); } @Override public void bookTicket() { System.out.println("明星订票"); } @Override public void sing() { System.out.println("明星唱歌"); } @Override public void collectMoney() { System.out.println("明星收钱"); } }
//静态代理对象去代理实际对象也实现Star接口 public class ProxyStar implements Star { private Star star; public ProxyStar() { super(); } public ProxyStar(Star star) { super(); this.star = star; } @Override public void confer() { System.out.println("代理面谈"); } @Override public void signContract() { System.out.println("代理签合同"); } @Override public void bookTicket() { System.out.println("代理订票"); } @Override public void sing() { star.sing(); } @Override public void collectMoney() { System.out.println("代理收钱"); } }
//静态代理测试 public class DonTaiDaiLi { public static void main(String[] args) { Star realStar = new RealStar(); Star proxy =new ProxyStar(realStar); proxy.bookTicket(); proxy.collectMoney(); proxy.sing(); }
动态代理利用了JDK API,动态地在内存中构建代理对象,从而实现对目标对象的代理功能。动态代理又被称为JDK代理或接口代理。
静态代理与动态代理的区别主要在:
特点:
动态代理对象不需要实现接口,但是要求目标对象必须实现接口,否则不能使用动态代理。
JDK中生成代理对象主要涉及的类有
static Object newProxyInstance(ClassLoader loader, //指定当前目标对象使用类加载器
Class<?>[] interfaces, //目标对象实现的接口的类型
InvocationHandler h //事件处理器
)
//返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
Object invoke(Object proxy, Method method, Object[] args)
// 在代理实例上处理方法调用并返回结果。
举例:明星代理
//定义代理类接口 public interface Star { /** * * 面谈 */ public void confer(); /** * 签合同 */ public void signContract(); /** * 订票 */ public void bookTicket(); /** * 唱歌 */ public void sing(); /** * 收钱 */ public void collectMoney(); }
//定义被代理目标对象实现Star接口 public class RealStar implements Star{ @Override public void confer() { System.out.println("明星面谈"); } @Override public void signContract() { System.out.println("明星签合同"); } @Override public void bookTicket() { System.out.println("明星订票"); } @Override public void sing() { System.out.println("明星唱歌"); } @Override public void collectMoney() { System.out.println("明星收钱"); } }
//动态代理对象去代理真实代理对象RealStar import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class StarHandler implements InvocationHandler{ Star realstar; public StarHandler(Star realstar) { super(); this.realstar = realstar; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object object= null; System.out.println("真正的方法执行前"); if (method.getName().equals("sing")) { object = method.invoke(realstar, args); } System.out.println("真正的方法执行后"); return object; } }
//动态代理测试 import java.lang.reflect.Proxy; public class DonTaiDaiLi { public static void main(String[] args) { Star realStar = new RealStar(); StarHandler handler = new StarHandler(realStar); Star proxy=(Star)Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{Star.class}, handler); proxy.sing(); } }
cglib is a powerful, high performance and quality Code Generation Library. It can extend JAVA classes and implement interfaces at runtime.
cglib (Code Generation Library )是一个第三方代码生成类库,运行时在内存中动态生成一个子类对象从而实现对目标对象功能的扩展。
cglib特点
cglib与动态代理最大的区别就是
使用cglib需要引入cglib的jar包,如果你已经有spring-core的jar包,则无需引入,因为spring中包含了cglib。
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.5</version>
</dependency>
举例:保存用户功能的动态代理实现
package com.cglib; public class UserDao{ public void save() { System.out.println("保存数据"); } }
package com.cglib; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class ProxyFactory implements MethodInterceptor{ private Object target;//维护一个目标对象 public ProxyFactory(Object target) { this.target = target; } //为目标对象生成代理对象 public Object getProxyInstance() { //工具类 Enhancer en = new Enhancer(); //设置父类 en.setSuperclass(target.getClass()); //设置回调函数 en.setCallback(this); //创建子类对象代理 return en.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("开启事务"); // 执行目标对象的方法 Object returnValue = method.invoke(target, args); System.out.println("关闭事务"); return null; } }
package com.cglib; import org.junit.Test; public class TestProxy { @Test public void testCglibProxy(){ //目标对象 UserDao target = new UserDao(); System.out.println(target.getClass()); //代理对象 UserDao proxy = (UserDao) new ProxyFactory(target).getProxyInstance(); System.out.println(proxy.getClass()); //执行代理对象方法 proxy.save(); } }
class com.cglib.UserDao
class com.cglib.UserDao$$EnhancerByCGLIB$$552188b6
开启事务
保存数据
关闭事务
代理模式相关知识
UML相关知识
原文:https://www.cnblogs.com/whymoney1000/p/10726162.html