失效链接处理 |
AOP的实现机制 PDF 下载
本站整理下载:
提取码:mkoq
相关截图:
主要内容:
2 AOP 里的公民
Joinpoint:拦截点,如某个业务方法。
Pointcut:Joinpoint 的表达式,表示拦截哪些方法。一个 Pointcut 对应多个 Joinpoint。 Advice: 要切入的逻辑。 Before Advice 在方法前切入。
After Advice 在方法后切入,抛出异常时也会切入。 After Returning Advice 在方法返回后切入,抛出异常则不会切入。
After Throwing Advice 在方法抛出异常时切入。
Around Advice 在方法执行前后切入,可以中断或忽略原有流程的执行。 公民之间的关系
织入器通过在切面中定义 pointcut 来搜索目标(被代理类)的 JoinPoint(切入点),然后
把要切入的逻辑(Advice)织入到目标对象里,生成代理类。
Joinpoint
Joinpoint
Joinpoint
Advice
Poincut
Poincut 织入器 代理类
目标
切面
AOP AOP
3 AOP 的实现机制
本章节将详细介绍 AOP 有各种实现机制。
3.1 动态代理
Java 在 JDK1.3 后引入的动态代理机制,使我们可以在运行期动态的创建代理类。使用
动态代理实现 AOP 需要有四个角色:被代理的类,被代理类的接口,织入器,和
InvocationHandler,而织入器使用接口反射机制生成一个代理类,然后在这个代理类中织入
代码。被代理的类是AOP里所说的目标,InvocationHandler是切面,它包含了Advice和Pointcut。
3.1.1 使用动态代理
那如何使用动态代理来实现 AOP。下面的例子演示在方法执行前织入一段记录日志的代
码,其中 Business 是代理类,LogInvocationHandler 是记录日志的切面,IBusiness, IBusiness2
是代理类的接口,Proxy.newProxyInstance 是织入器。
清单一:动态代理的演示
public static void main(String[] args) {
//需要代理的接口,被代理类实现的多个接口都必须在这里定义
Class[] proxyInterface = new Class[] { IBusiness.class,
IBusiness2.class };
//构建AOP的Advice,这里需要传入业务类的实例
LogInvocationHandler handler = new LogInvocationHandler(new
Business());
//生成代理类的字节码加载器
ClassLoader classLoader = DynamicProxyDemo.class.getClassLoader();
//织入器,织入代码并生成代理类
IBusiness2 proxyBusiness = (IBusiness2)
Proxy.newProxyInstance(classLoader, proxyInterface, handler);
//使用代理类的实例来调用方法。
接口
类
切入
逻辑
代理
类
proxyBusiness.doSomeThing2();
((IBusiness) proxyBusiness).doSomeThing();
}
/**
* 打印日志的切面
*/
public static class LogInvocationHandler implements InvocationHandler {
private Object target; //目标对象
LogInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//执行原有逻辑
Object rev = method.invoke(target, args);
//执行织入的日志,你可以控制哪些方法执行切入逻辑
if (method.getName().equals("doSomeThing2")) {
System.out.println("记录日志");
}
return rev;
} }
接口IBusiness和IBusiness2定义省略。
业务类,需要代理的类。
public class Business implements IBusiness, IBusiness2 {
@Override
public boolean doSomeThing() {
System.out.println("执行业务逻辑");
return true;
}
@Override
public void doSomeThing2() {
System.out.println("执行业务逻辑2");
}
}
输出
执行业务逻辑2
记录日志
执行业务逻辑
可以看到“记录日志”的逻辑切入到 Business 类的 doSomeThing 方法前了。
3.1.2 动态代理原理
本节将结合动态代理的源代码讲解其实现原理。动态代理的核心其实就是代理对象的生
成,即 Proxy.newProxyInstance(classLoader, proxyInterface, handler)。让
我们进入 newProxyInstance 方法观摩下,核心代码其实就三行。
清单二:生成代理类
//获取代理类
Class cl = getProxyClass(loader, interfaces);
//获取带有InvocationHandler参数的构造方法
Constructor cons = cl.getConstructor(constructorParams);
//把handler传入构造方法生成实例
return (Object) cons.newInstance(new Object[] { h });
其中 getProxyClass(loader, interfaces)方法用于获取代理类,它主要做了三件事情:在当
前类加载器的缓存里搜索是否有代理类,没有则生成代理类并缓存在本地 JVM 里。
清单三:查找代理类
// 缓存的key使用接口名称生成的List
Object key = Arrays.asList(interfaceNames);
synchronized (cache) {
do {
Object value = cache.get(key);
// 缓存里保存了代理类的引用
if (value instanceof Reference) {
proxyClass = (Class) ((Reference) value).get();
}
if (proxyClass != null) {
// 代理类已经存在则返回
return proxyClass;
} else if (value == pendingGenerationMarker) {
// 如果代理类正在产生,则等待
try {
cache.wait();
} catch (InterruptedException e) {
}
continue;
} else {
//没有代理类,则标记代理准备生成
cache.put(key, pendingGenerationMarker);
break; }
} while (true);
}
代理类的生成主要是以下这两行代码
|