Spring AOP基本用法2
Spring AOP 用法二
在上一篇中讲到通过xml配置ProxyFactoryBean
来创建代理对象,在这一篇中看看通过编程的方式配置ProxyFactory
。该类继承自ProxyCreatorSupport
(之前提到过该类提供了一些创建代理对象的基础方法),提供了配置目标对象,代理接口和通知的功能。
基本用法
1 | DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); |
通过以上代码,我们创建出了最终的代理对象。大致步骤如下:
- 通过构造函数,传入目标对象,创建代理工厂对象
- 添加通知
- 获取代理对象
- 调用代理对象的方法
执行结果:
1 | Before method advice |
打印结果也说明了我们的代理对象正常工作,先执行了前置通知,再调用了目标对象的方法。
最重要的获取代理对象的方法都是在父类中完成的,与ProxyFactoryBean
类似,该类只是提供了另外一种配置的方式。
构造函数
构造函数是这个类使用比较频繁的方法。可以通过目标对象,代理接口,以及通知来使用构造函数。
ProxyFactory(Object target)
通过此方法将根据目标对象创建ProxyFactory
对象,并且会代理目标对象所有的接口。
1 | public ProxyFactory(Object target) { |
ProxyFactory(Class<?>... proxyInterfaces)
传入代理接口数组构造ProxyFactory
对象,这种情况下只设置了代理接口,则必须手动设置通知,否则在创建代理的过程中无法通过校验。
目前创建的Jdk动态代理和cglib代理都判断了通知和目标对象不能同时为空。
Jdk代理:
1 | public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException { |
cglib代理:
1 | public CglibAopProxy(AdvisedSupport config) throws AopConfigException { |
如果设置了拦截器,由于在最终调用目标对象方法时,没有判断目标对象是否为空,所以会报空指针异常。
ProxyFactory(Class<?> proxyInterface, Interceptor interceptor)
此方法同时设置代理接口和拦截器。由于没有目标对象,也会出现上面的空指针异常情况。针对只有一个拦截器的情况下,此方法创建代理对象比较方法。
ProxyFactory(Class<?> proxyInterface, TargetSource targetSource)
此方法根据代理接口和TargetSource
创建ProxyFactory
对象。
getProxy
方法
通过此方法将会获取最终的代理对象。
通过构造函数创建ProxyFactory
对象后,还需要根据实际情况设置目标对象、代理接口以及通知,然后再调用getProxy
方法获取代理对象。
Object getProxy()
无参方法
根据ProxyFactory
的设置创建代理对象。可以重复调用此方法,如果添加或删除接口,添加或者删除拦截器,效果会有所不同。由于多次调用使用的是同一个ProxyFactory
对象,只是配置不同,在调用代理对象的方法时,会影响到代理对象的执行过程。
此方法使用默认类加载器来创建代理,一般是线程上下文类加载器。
Object getProxy(ClassLoader classLoader)
跟上面的方法类似,只是使用指定的类加载器。
static <T> T getProxy(Class<T> proxyInterface, Interceptor interceptor)
此方法是静态方法,根据指定的代理接口和拦截器创建代理。内部使用ProxyFactory(Class<?> proxyInterface, Interceptor interceptor)
方法创建ProxyFactory
对象之后再调用无参getProxy()
方法。
static <T> T getProxy(Class<T> proxyInterface, TargetSource targetSource)
此静态方法为指定的TargetSource
创建代理,该代理会实现指定的接口。方法内部使用new ProxyFactory(proxyInterface, targetSource)
方法创建ProxyFactory
对象之后再调用无参getProxy()
方法。
static Object getProxy(TargetSource targetSource)
该静态方法为指定的TargetSource
创建一个代理,扩展TargetSource
的目标类。由于没有指定接口,所以方法内部会设置proxyTargetClass
为true
,通过cglib来创建目标对象的子类。
以下代码用来判断是否用jdk代理还是cglib来生成代理。
1 | if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { |