说明:图片是我其它地方博客里的java
package dproxy; /** *抽象主题 **/ interface Subject { void subjectMethod(int a,int b); } /** *具体主题 **/ /** *实现了Subject接口,而且覆盖了subjectMethod方法 **/ package dproxy; public class RealSubject implements Subject { //Joinpoint链接点 @Override public void subjectMethod(int a, int b) { // TODO Auto-generated method stub System.out.println(a+"+"+b +"="+(a+b)); } } /** *代理处理 **/ package dproxy; import java.lang.reflect.InvocationHandler; //Aspect(方面)??? public class ProxyHandler implements InvocationHandler { private Object subject; public ProxyHandler(Object subject) { // TODO Auto-generated constructor stub this.subject = subject; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { before(); // TODO Auto-generated method stub System.out.println("调用真实主题的方法"); /** *用反射机制调用了realMethod方法 **/ method.invoke(subject, args); after(); return null; } //Advice(通知) public void before() { System.out.println("代理前的处理操做"); } //Advice(通知) public void after() { System.out.println("代理后的处理操做"); } }
invoke方法参数说明: invoke
方法的第一个参数是 proxy
是 Proxy.newProxyInstance
建立的对象,我在网上看到不少文章说这个参数是被代理类的对象即RealSubject的对象,这种说法是错误的,你们能够用RTTI
对proxy
进行了解,它确实是 Proxy.newProxyInstance
建立的对象
构造器说明: ProxyHandler()
构造器接受一个参数,这个参数是被代理类即RealSubject
的对象。
invoke内部解析: 咱们在 invoke
函数里面 经过 method.invoke(subject, args);
调用了真实主题,即被代理对象的某一个方法,注意 invoke
的第二个参数是 method
它指明调用被代理对象的哪个方法,第三个参数是该方法的参数。spring
package dproxy; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class Client { public static void main(String[] args) { // TODO Auto-generated method stub /** *建立真实主题 **/ Subject realSubject = new RealSubject(); /** *建立代理处理器 **/ ProxyHandler handler = new ProxyHandler(realSubject); /** *建立代理对象 **/ Subject proxy = (Subject) Proxy.newProxyInstance(realSubject.getClass() .getClassLoader(), realSubject.getClass().getInterfaces(), handler); /** *调用动态建立的代理对象的动态生成的subjectMethod方法 **/ proxy.subjectMethod(3, 5); //执行了3+5操做 并在该操做先后调用了附加方法 } }
说明1:Proxy.newProxyInstance建立了一个代理对象,而且以Subject的身份去调用一个貌似和Subject类如出一辙的接口subjectMethod因为 proxy对象是Subject类型的 即 Subject proxy ,因此咱们执行 proxy.subjectMethod(3, 5);时感受不到在用代理。
说明2:咱们建立proxy时传入了一个handler对象。在这个对象里咱们调用了被代理的那个对象的方法,而且在其先后附加了方法。ide
执行流程:函数
1 在Client
建立了一个被代理的对象 realSubject
2 建立了一个代理处理器,这里是代理处理器,并非代理类,由于它不是Subject
类型,也没有和Subject
内部长的同样的函数因此它不是代理对象,可是它对真实对象,即realSubject
对象的调用时由这个对象代替代理类来作的。也就是代理类将对被代理对象的调用的职责委托给了这个代理处理器
3 Proxy
类建立了一个对象,而后这个类经过 java
反射机制 将建立的这个对象变的类型变成了Subject
,建立的这个对象内部有一个代理处理器对象handler
4 由3建立的那个代理对象,执行proxy.subjectMethod(3, 5);
以Subject
的身份调用了一个和Subject
接口中的某个函数长的同样的一个函数,这是由于proxy
是Subject
类型的一个对象
5 proxy
在subjectMethod
函数内部将对被代理对象的调用委托给了代理处理器对象handler
this
和spring AOP
的关系AOP
中的 Advice通知
就是咱们在被代理方法执行先后附加的方法AOP
中的 Joinpoint链接点
就是咱们须要执行的那个 3+5的方法AOP
中的 Aspect方面
若是咱们将全部的 Advice通知 提取出来放在 一个类中就构成 了 Aspect
方面 AOP
中的 Pointcut切入点
是全部符合相同规则的链接点的集合,例如全部以do开头的方法,切入点内包含一套规则用来讲明该切入点包含哪些连接点AOP
中的Introduction(引介)
引介是一种特殊的通知在不修改类代码的前提下, Introduction
能够在运行期为类动态地添加一些方法或Field
AOP
中的Target(目标对象)
代理的目标对象(要加强的类) AOP
中的织入 Weaving
把切面应用到目标对象并建立新的代理对象的过程。切面在指定的链接点被织入到目标对象中。织入能够在对象生命周期的编译期、类加载期、运行期完成。Spring AOP
由于采用动态代理,因此是在 运行期 完成织入。AOP
中的Proxy(代理)
一个类被AOP织入加强后,就产生一个结果代理类spa