说明:图片是我其它地方博客里的
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
它指明调用被代理对象的哪一个方法,第三个参数是该方法的参数。
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对象。在这个对象里我们调用了被代理的那个对象的方法,并且在其前后附加了方法。
执行流程:
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
和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织入增强后,就产生一个结果代理类
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。