因为学习 spring框架的 AOP 所以,这里复习下动态代理,但是 spring 的底层动态代理实现是 cglib,jdk 这种呢可以引导新手入门
spring AOP 横向抽取机制 最典型的应用当属 log ,transaction 了,具体可以从配置文件的配置以及注解看出
首先基于 jdk 的动态代理需要借助于
jdk 中 reflect 包下(java.lang.reflect.Proxy)的 Proxy
以及(java.lang.reflect.InvocationHandler) InvacationHandler
去生成代理对象。
局限性是这种动态代理只适用于对有接口的类实现动态代理
原理其实是,利用反射机制先生成要被代理对象的同级对象然后对这个同级对象进行增强
所以这里需要传入接口
下面是代码部分详解:
首先我们定义一个简单的 动物接口 IAnimal 里面有一个简单方法 move
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.ghc.test; public interface IAnimal { void move(); }
然后呢,我们定义一个要被代理的类 Cat,这个类实现了 IAnimal 接口
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.ghc.test; public class Cat implements IAnimal { @Override public void move() { System.out.println("cat run..."); } }
接下来就是我们 处理器的定义了,这个唤醒处理器呢有个规范就是必须实现 接口 java.lang.reflect.InvocationHandler;
覆写里面的 invoke 方法,并且在 invoke 方法中做我们的增强,具体代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.ghc.test; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class AnimalInvocationHandler implements InvocationHandler { // 定义要被代理的类 private Object tar; public AnimalInvocationHandler(Object tar){ this.tar=tar; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("前置增强处......"); Object result = method.invoke(tar,args); System.out.println("后置增强处......"); return result; } public Object getProxyInstance(){ return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),tar.getClass().getInterfaces(),this); } }
当然,上面其中一个方法 getProxyInstance 其实是可以定义在使用的地方的。这都不是重点
重点来了,就是我们如何使用呢:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import com.ghc.test.AnimalInvocationHandler; import com.ghc.test.Cat; import com.ghc.test.IAnimal; import org.junit.Test; public class DynamicProxyTest { @Test public void testCatProxy(){ //先创建要被代理的对象 Cat cat = new Cat(); AnimalInvocationHandler animalInvocationHandler=new AnimalInvocationHandler(cat); IAnimal catProxy = (IAnimal) animalInvocationHandler.getProxyInstance(); catProxy.move(); } }
结果如图: