Spring AOP 使用的其中一个底层技术就是 Java 的动态代理技术。Java 的动态代理技术主要围绕两个类进行的
- java.lang.reflect.InvocationHandler
- java.lang.reflect.Proxy
首先从代码层面说明 Java 动态代理是如何实现的,
业务逻辑接口:
- /**
- * 创建一个人的接口,其中有一个吃的方法
- */
- public interface Person {
- public void eat();
- }
创建一个实现该业务接口的类:
- /**
- * 人接口的实现,实现吃饭的方法
- */
- public class PersonImpl implements Person {
- @Override
- public void eat() {
- System.out.println("吃主食、吃菜、喝汤...");
- }
- }
此时,如果正常情况如果想要调用 Person 这个接口,直接 new 它的实现类然后调用 eat 方法即可,但是如果想要实现一个 Person 的代理,并且在 eat 方法前后进行一些工作就需要使用 Proxy 和 InvovationHandler;
InvocationHandler 接口的实现类,(代理类中额外逻辑的实现就需要在这里进行)
- /**
- * 代理类的额外逻辑实现类
- */
- public class InvocationHandlerImpl implements InvocationHandler {
- Person person;
- public InvocationHandlerImpl(Person person) {
- this.person = person;
- }
- @Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- if(method.getName().equalsIgnoreCase("eat")) {
- System.out.println("洗手...");
- method.invoke(person, args);
- System.out.println("刷牙");
- }
- return person;
- }
- }
接下来就是使用 Proxy 生成代理类,Proxy 需要业务逻辑接口,代理类额外实现逻辑 InvocationHandler 实现类
- /**
- * 代理类产生并且测试
- */
- public class ProxyGenerate {@Test public void proxyTest() {
- Person person = new PersonImpl();
- InvocationHandler invocationHandler = new InvocationHandlerImpl(person);
- Person personProxy = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class[] {
- Person.class
- },
- invocationHandler);
- personProxy.eat();
- }
- }
输出内容如下:
代理类已经成功的完成代理。
AOP 的功能就是在一个方法前、后、异常抛出等地方添加逻辑,与上面的过程是一样的,所以这个技术就被用来实现 Spring AOP 的一个技术,但是这个只针对接口实现,如果想要给一个类添加 AOP 的逻辑,这个 Proxy 动态代理的技术暂时无法适用,Spring AOP 适用了 CGLIB,支持类的动态代理,但是不属于这一次的讨论范畴。
知道怎么用了之后是不是对 Proxy 这个感觉很神奇,想知道是如何实现的呢,可以深入了解一下 newProxyInstance 这个方法:
找到上述内容,可以看到这个是动态生成代理类字节数组的方法,所以我们可以通过这个方法了解到动态生成的代理类的结构:
- /**
- * 代理类产生并且测试
- */
- public class ProxyGenerate {@Test public void proxyWatch() {
- byte[] classByte = ProxyGenerator.generateProxyClass("PersonDynamicProxy", new Class[] {
- Person.class
- });
- try {
- FileOutputStream var1 = new FileOutputStream("PersonDynamicProxy" + ".class");
- var1.write(classByte);
- var1.close();
- } catch(IOException var2) {
- throw new InternalError("I/O exception saving generated file: " + var2);
- }
- }
- }
执行上述代码会生成动态代理对象的. class 文件
反编译(jd-gui,idea)之后就可以看到动态代理类的结构:
- //
- // Source code recreated from a .class file by IntelliJ IDEA
- // (powered by Fernflower decompiler)
- //
- import com.smart.beanfactory.Person;
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- import java.lang.reflect.Proxy;
- import java.lang.reflect.UndeclaredThrowableException;
- public final class PersonDynamicProxy extends Proxy implements Person {
- private static Method m1;
- private static Method m3;
- private static Method m0;
- private static Method m2;
- public PersonDynamicProxy(InvocationHandler var1) throws {
- super(var1);
- }
- public final boolean equals(Object var1) throws {
- try {
- return ((Boolean) super.h.invoke(this, m1, new Object[] {
- var1
- })).booleanValue();
- } catch(RuntimeException | Error var3) {
- throw var3;
- } catch(Throwable var4) {
- throw new UndeclaredThrowableException(var4);
- }
- }
- public final void eat() throws {
- try {
- super.h.invoke(this, m3, (Object[]) null);
- } catch(RuntimeException | Error var2) {
- throw var2;
- } catch(Throwable var3) {
- throw new UndeclaredThrowableException(var3);
- }
- }
- public final int hashCode() throws {
- try {
- return ((Integer) super.h.invoke(this, m0, (Object[]) null)).intValue();
- } catch(RuntimeException | Error var2) {
- throw var2;
- } catch(Throwable var3) {
- throw new UndeclaredThrowableException(var3);
- }
- }
- public final String toString() throws {
- try {
- return (String) super.h.invoke(this, m2, (Object[]) null);
- } catch(RuntimeException | Error var2) {
- throw var2;
- } catch(Throwable var3) {
- throw new UndeclaredThrowableException(var3);
- }
- }
- static {
- try {
- m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] {
- Class.forName("java.lang.Object")
- });
- m3 = Class.forName("com.smart.beanfactory.Person").getMethod("eat", new Class[0]);
- m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
- m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
- } catch(NoSuchMethodException var2) {
- throw new NoSuchMethodError(var2.getMessage());
- } catch(ClassNotFoundException var3) {
- throw new NoClassDefFoundError(var3.getMessage());
- }
- }
- }
可以看出来,动态代理类首先通过反射的技术,将源接口中的方法均设置为其静态属性(Method),然后针对每个方法进行重写。
重写的逻辑是使用 invocationHandler 接口的 invoke 方法实现,每个 invoke 方法在绑定相应的反射出来的静态属性即可。
举例,比如上面 Person 接口的 eat 被反射未 m3 的静态属性中,重写 eat()方法是调用方法为 invoke(this, m3, args),其中 invoke 中会有额外添加的一些逻辑,
来源: http://www.cnblogs.com/weixliu/p/7353260.html