动态代理的两种实现

mac2024-04-17  33

1:动态代理

1:自我看法

什么是动态代理,简单的讲就是让别人帮你做事情。同时别人在做的时候,顺便可以做的其他事情,而这些事情就是加强,因为自己没法做。

2:例子

举个例子,小明是班长,小红是小明的同班同学,新学期到了,每个人都要交班费,(当然小明和小红都要交),显然”交班费“这是他们共有的方法,由于小红当天没有带钱,第二天又不想单独去交,所以交给小明,此时,小明就是成为了小红的交钱的代理者(拿到小红的钱,帮她交钱),路上小明看见了自己暗恋的小芳,主动上前告白(我们视为“告白”,是小明的一个方法,显然小红相对于小明没有),告白完之后,就去交钱了。 从上面这个过程中我可以知道: 小明干了两件事1:帮小红交钱,2:告白 小红做了一件事1:交钱

3:总结

从上面我们知道,小明帮小红做事,小明是需要小红的一些东西的,除此之外,小红的身份是可以变换的,可以是小芳,也可以是小兰,所以此时,小明就相当于工厂,小红,小兰,小芳相当工厂中的货物。因此,在我们进行代理时,只需要将方法参数进行变化就可以实现对不同类的代理。

2:动态代理的分类

动态代理分为jdk动态代理与cglib代理。 jdk代理:由java的反射机制实现,被代理的类必须至少实现一个接口,否则无法被代理 cglib代理:通过地层的asm实现,可以代理实现接口的类,也可以代理不实现接口的类,但该类不能被final修饰。

3:动态代理的使用

当我们写了一个类时,觉得他当前的功能不太全面,但这个类当前无法更改,我们又要有一些新的功能,如方法前后查看日志等等。就可以使用代理对方法进行加强,即使用该方法时我们又查看了日志等情况。

JDK动态代理

1:使用代理工厂进行实现

1.1:主要方法的参数

@创建代理对象的类。 @代理方式:基于实现接口的类的动态代理 @涉及类:Proxy @提供方:JDK @创建代理对象涉及方法:newProxyInstance()-----创建代理对象的方法 该方法是Proxy类中的静态方法(静态方法:不需要创建类,直接 类.方法即可)

参数1: classLoader:类加载器(XX.getClass().getClassLoader) 用于加载代理对象的字节码(代理对象和被代理对象使用相同的类加载器) 参数2: class[]: 用于使代理对象和被代理对象有相同的方法 参数3: InvocationHandler: 一般写该接口的实现类(但当前ProxyFactory不是实现其实现类, 本类是工厂模式)自己创建一个实现InvocationHandler接口的类, 该类实际上是一个 “中介类”,用来写增强代码

@要求:被代理类(目标对象)必须实现一个接口

1.2:被代理类实现的接口
public interface ImProducer { public void before(); public void after() ; }
1.3:被代理类
public class Producer implements ImProducer{ public void before(){ System.out.println("before"); } public void after() { System.out.println("after"); } }
1.4:代理工厂(产生代理对象)
public class ProxyFactory { //设置一个目标对象 private Object target; public ProxyFactory(Object target){ this.target=target; } //返回目标对象的一个代理对象 //这个方法函数是自己写的 public Object getProxy() { //返回的newProxyInstance这个方法函数是proxy类中的静态方法 return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { /** * 作用:执行被代理对象的所以有方法都会经过该方法 * * @param proxy :代理对象的引用,代表动态代理对象 * @param method :当前执行的方法 * @param args :当前执行方法所需要的参数 * @return 与被代理对象方法的返回值相同 * @throws Throwable */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object returnValue = null; //方法1: //方法2: //...... //执行目标对象方法 returnValue = method.invoke(target,args); //方法3: //方法4: //...... //以上除目标方法外的方法,都是增强方法 return returnValue; } }); } }
1.5:测试
//目标对象 ImProducer target = new Producer(); //获得代理对象:参数可以是其他类,该方法为模板,只需要给对应的目标对象 ImProducer proxy = (ImProducer) new ProxyFactory(target).getProxy();//最好用接口 //jdk为我们的生成了$Proxy0的代理类,当多个代理类时$Proxy0后面数字可以增加,以此区别代理类 // 如$Proxy1,$Proxy2.。。。。。 proxy.before(); proxy.after();

1:实现InvocationHandler接口的动态代理

被代理类实现的接口和被代理类与上面工厂模式的动态代理相同。

1.1:InvocationHandler接口的实现类
public class ExtendInvocationHandler implements InvocationHandler { //设置一个目标对象 private Object target; public ExtendInvocationHandler(Object target){ this.target=target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { /** * 作用:执行被代理对象的所以有方法都会经过该方法 * * @param proxy :代理对象的引用,代表动态代理对象 * @param method :当前执行的方法 * @param args :当前执行方法所需要的参数 * @return 与被代理对象方法的返回值相同 * @throws Throwable */ Object returnValue = null; //方法1: //方法2: //...... //执行目标对象方法 returnValue = method.invoke(target,args); //方法3: //方法4: //...... //以上除目标方法外的方法,都是增强方法 return returnValue; } }
1.2: 测试
//目标对象 ImProducer target = new Producer(); InvocationHandler handler=new ExtendInvocationHandler(target); ImProducer proxy1 = (ImProducer)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler); proxy1.before(); proxy1.after();

Cglib动态代理

由于JDK只能代理实现接口的类,而在实际开发中一些类没有代理接口但需要增强,所以cglib弥补了这一缺点,而cglib代理方式是通过“继承”被代理类,将其作为父类,然后继承被代理类的所有的公开方法,然后重写这些方法,在重写时对这些方法增强。通常情况下,要实现MethodInterceptor接口。

1.1:主要参数

@创建代理对象的子类。 @代理方式:基于子类的动态代理 @涉及类:Enhancer @提供方:cglib库 @创建代理对象涉及方法:create()-----创建代理对象的方法

参数1: class:字节码 指定的被代理对象的字节码 参数2: Callback:用于提供增强的代码 一般写该MethodInterceptor接口的实现类 @要求:代理的对象不是最终类,针对类来进行代理(被代理类不需要实现接口)
1.2:被代理类
public class Producer implements ImProducer{ public void before(){ System.out.println("before"); } public void after() { System.out.println("after"); } }
1.3:实现MethodInterceptor
public class ProxyFactory implements MethodInterceptor{ public Object getProxy(Class cls) { //1.创建Cglib中enhancer增强类对象 Enhancer en = new Enhancer(); //2.设置要增强的类型(被代理类也就是目标对象) en.setSuperclass(cls); //3.定义代理逻辑对象为当前对象(类对象),但要求当前对象实现MethodInterceptor接口 en.setCallback(this); //生成代理对象并返回 Object proxy = en.create(); return proxy; } public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object returnValue = null; //方法1: //方法2: //...... //执行目标对象方法 returnValue = methodProxy.invokeSuper(proxy,args); //方法3: //方法4: //...... //以上除目标方法外的方法,都是增强方法 return returnValue; } }
1.4:测试
ProxyFactory proxyFactory =new ProxyFactory(); Producer proxy=(Producer) proxyFactory.getProxy(Producer.class); proxy.before(); proxy.after();
最新回复(0)