Spring 中AOP 特性详解

Spring 框架的设计理念与设计模式分析--- SpringAOP 特性详解


动态代理的实现原理

要了解 Spring AOP 就必须先了解的动态代理的原理,因为 AOP 就是基于动态代理实现的。动态代理还要从 JDK 本身说起。

Jdk java.lang.reflect 包下有个 Proxy 类,它正是构造代理类的入口。这个类的结构入下:


16. Proxy 类结构

从上图发现最后面四个是公有方法。而最后一个方法 newProxyInstance 就是创建代理对象的方法。这个方法的源码如下:


清单 6. Proxy. newProxyInstance

public static Object newProxyInstance(ClassLoader loader,

Class<?>[] interfaces,

InvocationHandler h)

throws IllegalArgumentException {

if (h == null) {

throw new NullPointerException();

}

Class cl = getProxyClass(loader, interfaces);

try {

Constructor cons = cl.getConstructor(constructorParams);

return (Object) cons.newInstance(new Object[] { h });

} catch (NoSuchMethodException e) {

throw new InternalError(e.toString());

} catch (IllegalAccessException e) {

throw new InternalError(e.toString());

} catch (InstantiationException e) {

throw new InternalError(e.toString());

} catch (InvocationTargetException e) {

throw new InternalError(e.toString());

}

}

这个方法需要三个参数:ClassLoader,用于加载代理类的 Loader 类,通常这个 Loader 和被代理的类是同一个 Loader 类。Interfaces,是要被代理的那些那些接口。InvocationHandler,就是用于执行除了被代理接口中方法之外的用户自定义的操作,他也是用户需要代理的最终目的。用户调用目标方法都被代理到 InvocationHandler 类中定义的唯一方法 invoke 中。这在后面再详解。

下面还是看看 Proxy 如何产生代理类的过程,他构造出来的代理类到底是什么样子?下面揭晓啦。


17. 创建代理对象时序图

其实从上图中可以发现正在构造代理类的是在 ProxyGenerator generateProxyClass 的方法中。ProxyGenerator 类在 sun.misc 包下,感兴趣的话可以看看他的源码。

假如有这样一个接口,如下:


清单 7. SimpleProxy

public interface SimpleProxy {

public void simpleMethod1();

public void simpleMethod2();

}

代理来生成的类结构如下:


清单 8. $Proxy2

public class $Proxy2 extends java.lang.reflect.Proxy implements SimpleProxy{

java.lang.reflect.Method m0;

java.lang.reflect.Method m1;

java.lang.reflect.Method m2;

java.lang.reflect.Method m3;

java.lang.reflect.Method m4;

int hashCode();

boolean equals(java.lang.Object);

java.lang.String toString();

void simpleMethod1();

void simpleMethod2();

}

这个类中的方法里面将会是调用 InvocationHandler invoke 方法,而每个方法也将对应一个属性变量,这个属性变量 m 也将传给 invoke 方法中的 Method 参数。整个代理就是这样实现的。

Spring AOP 如何实现

从前面代理的原理我们知道,代理的目的是调用目标方法时我们可以转而执行 InvocationHandler 类的 invoke 方法,所以如何在 InvocationHandler 上做文章就是 Spring 实现 Aop 的关键所在。

Spring Aop 实现是遵守 Aop 联盟的约定。同时 Spring 又扩展了它,增加了如 PointcutAdvisor 等一些接口使得更加灵活。

下面是 Jdk 动态代理的类图:


18. Jdk 动态代理的类图

上图清楚的显示了 Spring 引用了 Aop Alliance 定义的接口。姑且不讨论 Spring 如何扩展 Aop Alliance,先看看 Spring 如何实现代理类的,要实现代理类在 Spring 的配置文件中通常是这样定一个 Bean 的,如下:


清单 9. 配置代理类 Bean

<bean id="testBeanSingleton"

class="org.springframework.aop.framework.ProxyFactoryBean">

<property name="proxyInterfaces">

<value>

org.springframework.aop.framework.PrototypeTargetTests$TestBean

</value>

</property>

<property name="target"><ref local="testBeanTarget"></ref> </property>

<property name="singleton"><value>true</value></property>

<property name="interceptorNames">

<list>

<value>testInterceptor</value>

<value>testInterceptor2</value>

</list>

</property>

</bean>

配置上看到要设置被代理的接口,和接口的实现类也就是目标类,以及拦截器也就在执行目标方法之前被调用,这里 Spring 中定义的各种各样的拦截器,可以选择使用。

下面看看 Spring 如何完成了代理以及是如何调用拦截器的。

前面提到 Spring Aop 也是实现其自身的扩展点来完成这个特性的,从这个代理类可以看出它正是继承了 FactoryBean ProxyFactoryBeanFactoryBean 之所以特别就在它可以让你自定义对象的创建方法。当然代理对象要通过 Proxy 类来动态生成。

下面是 Spring 创建的代理对象的时序图:


19.Spring 代理对象的产生

Spring 创建了代理对象后,当你调用目标对象上的方法时,将都会被代理到 InvocationHandler 类的 invoke 方法中执行,这在前面已经解释。在这里 JdkDynamicAopProxy 类实现了 InvocationHandler 接口。

下面再看看 Spring 是如何调用拦截器的,下面是这个过程的时序图:


20.Spring 调用拦截器

以上所说的都是 Jdk 动态代理,Spring 还支持一种 CGLIB 类代理,感兴趣自己看吧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值