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中会有额外添加的一些逻辑,

Java动态代理学习【Spring AOP基础之一】的更多相关文章

  1. java:struts框架2(方法的动态和静态调用,获取Servlet API三种方式(推荐IOC(控制反转)),拦截器,静态代理和动态代理(Spring AOP))

    1.方法的静态和动态调用: struts.xml: <?xml version="1.0" encoding="UTF-8"?> <!DOCT ...

  2. java中代理,静态代理,动态代理以及spring aop代理方式,实现原理统一汇总

    若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理 ,这种情况下的代理类通常都是我们在Java代码中定义的. 通常情况下, 静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类. ...

  3. JAVA 动态代理学习记录

    打算用JAVA实现一个简单的RPC框架,看完RPC参考代码之后,感觉RPC的实现主要用到了两个方面的JAVA知识:网络通信和动态代理.因此,先补补动态代理的知识.---多看看代码中写的注释 参考:Ja ...

  4. Java动态代理学习

    动态代理类 Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类: 1.Interface InvocationHandler 该接口中仅定义了一个方法: Objec ...

  5. 从动态代理到Spring AOP(中)

    一.前言 上一章节主要介绍了JDK动态代理和CGLIB动态代理:https://www.cnblogs.com/GrimMjx/p/11194283.html 这一章主要结合我们之前学习的动态代理的基 ...

  6. 从动态代理到Spring AOP(上)

    一.前言 虽然平时日常开发很少用到动态代理,但是动态代理在底层框架等有着非常重要的意义.比如Spring AOP使用cglib和JDK动态代理,Hibernate底层使用了javassit和cglib ...

  7. java动态代理与老式AOP实现

    JAVA的动态代理 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会 ...

  8. java 动态代理学习(Proxy,InvocationHandler)

    前几天看到java的动态代理机制,不知道是啥玩意,然后看了看.死活不知道 invoke(Object proxy, Method m, Object[] args)种的proxy是个什么东西,放在这里 ...

  9. 反射实现 AOP 动态代理模式(Spring AOP 的实现原理)

    枚举 在某些情况下,一个类的对象是有限而且固定的,比如季节类,它只有4个对象.这种实例有限而且固定的类,在Java里被称为枚举类. 枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则,编 ...

随机推荐

  1. 从Android源码的角度分析Binder机制

    欢迎访问我的个人博客,原文链接:http://wensibo.top/2017/07/03/Binder/ ,未经允许不得转载! 前言 大家好,好久不见,距离上篇文章已经有35天之久了,因为身体不舒服 ...

  2. 读书共享 Primer Plus C-part 7

    第十章  数组和指针 1.关于二维数组跟指针 #include<stdio.h> int main() { ][]={{,,,},{,,,},{,,,}}; ; ;i< ;i++) ...

  3. 一张图告诉你angular2所有知识点

    忙活了半年,从angular2.0到现在angular4.2.从没AOT到有AOT.我想说,angular2的学习曲线真的有点陡峭.只能说,angular2是一个比较完整的框架,框架就是这样,一大堆条 ...

  4. 流行框架angular

    ---恢复内容开始--- 一.angular是什么 一款非常优秀的前端高级js框架,由谷歌团队负责开发 angular是通过新的属性和表达扩展了html angular可以构建一个单一页面应用程序(s ...

  5. Vue.js 基本功能了解

    一.写在前面 隔了这么久才来出Vue的第二篇文章,真是堕落了,自己先惩罚下/(ㄒoㄒ)/~~ 回过头看自己第一篇相关文章<初试 Vue.js>(http://www.cnblogs.com ...

  6. 简单的使用Seajs

    什么是Seajs Seajs是一个加载器 http://yslove.net/seajs/ 遵循 CMD 规范模块化开发,依赖的自动加载.配置的简洁清晰. 兼容性 Chrome 3+ Firefox ...

  7. Chrome浏览器扩展开发系列之八:Chrome扩展的数据存储

    Google Chrome浏览器扩展可以使用如下任何一种存储机制: HTML5的localStorage API实现的本地存储(此处略) Google的chrome.storage.* API实现的浏 ...

  8. linux可用更新源

    Kali 2.0更新源kali-rolling:#中科大deb http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contribde ...

  9. Go学习笔记(一)Let's 干吧

    加 Golang学习 QQ群共同学习进步成家立业 ^-^ 群号:96933959 简介     Go是Google开发的一种 静态强类型.编译型,并发型,并具有垃圾回收功能的编程语言.为了方便搜索和识 ...

  10. springmvc(一) springmvc框架原理分析和简单入门程序

    springmvc这个框架真的非常简单,感觉比struts2还更简单,好好沉淀下来学习~ --WH 一.什么是springmvc? 我们知道三层架构的思想,并且如果你知道ssh的话,就会更加透彻的理解 ...