Spring框架的设计理念与设计模式(7)-Spring中AOP特性与实现

本文深入探讨了Spring框架中的AOP(面向切面编程)特性,并详细解析了其背后的动态代理实现原理。通过理解JDK动态代理机制,读者可以更好地掌握Spring如何利用这些技术来实现复杂的业务逻辑拦截。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关键词:Spring,AOP,Proxy,代理,拦截器
上一章:[b]Spring框架的设计理念与设计模式(6)-Ioc容器及BeanFactory工厂[/b] [url]http://javapub.iteye.com/blog/751635[/url]
下一章:[b]Spring框架的设计理念与设计模式(8)-代理模式[/b] [url]http://javapub.iteye.com/blog/751652[/url]

[b]动态代理的实现原理[/b]

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

在Jdk的java.lang.reflect包下有个Proxy类,它正是构造代理类的入口。这个类的结构入下:
[img]http://www.kutoku.info/images/java/100831/spring15.gif[/img]

从上图发现最后面四个是公有方法。而最后一个方法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如何产生代理类的过程,他构造出来的代理类到底是什么样子?下面揭晓啦。
[img]http://www.kutoku.info/images/java/100831/spring16.gif[/img]
其实从上图中可以发现正在构造代理类的是在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参数。整个代理就是这样实现的。

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

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

下面是Jdk动态代理的类图:
[img]http://www.kutoku.info/images/java/100831/spring17.gif[/img]
上图清楚的显示了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>truevalue>property>

<property name="interceptorNames">

<list>

<value>testInterceptorvalue>

<value>testInterceptor2value>

<list>

<property>

<bean>


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

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

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

下面是Spring创建的代理对象的时序图:
[img]http://www.kutoku.info/images/java/100831/spring18.gif[/img]
Spring创建了代理对象后,当你调用目标对象上的方法时,将都会被代理到InvocationHandler类的invoke方法中执行,这在前面已经解释。在这里JdkDynamicAopProxy类实现了InvocationHandler接 口。

下面再看看Spring是如何调用拦截器的,下面是这个过程的时序图:
[img]http://www.kutoku.info/images/java/100831/spring19.gif[/img]
以上所说的都是Jdk动态代理,Spring还支持一种CGLIB类代理,感兴趣自己看吧。

[b]目录--Spring框架的设计理念与设计模式[/b]
[b]Spring框架的设计理念与设计模式(1)-Spring的架构[/b] [url]http://javapub.iteye.com/blog/751539[/url]
[b]Spring框架的设计理念与设计模式(2)-Spring的设计理念[/b] [url]http://javapub.iteye.com/blog/751545[/url]
[b]Spring框架的设计理念与设计模式(3)-Bean组件[/b] [url]http://javapub.iteye.com/blog/751550[/url]
[b]Spring框架的设计理念与设计模式(4)-Context组件[/b] [url]http://javapub.iteye.com/blog/751625[/url]
[b]Spring框架的设计理念与设计模式(5)-Core组件[/b] [url]http://javapub.iteye.com/blog/751627[/url]
[b]Spring框架的设计理念与设计模式(6)-Ioc容器及BeanFactory工厂[/b] [url]http://javapub.iteye.com/blog/751635[/url]
[b]Spring框架的设计理念与设计模式(7)-Spring中AOP特性与实现[/b] [url]http://javapub.iteye.com/blog/751642[/url]
[b]Spring框架的设计理念与设计模式(8)-代理模式[/b] [url]http://javapub.iteye.com/blog/751652[/url]
[b]Spring框架的设计理念与设计模式(9)-策略模式[/b] [url]http://javapub.iteye.com/blog/751653[/url]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值