以编程的方式使用spring提供的AOP功能,下面是一个简单的例子:
package com.zws.spring.core.aop.springAop;import java.lang.reflect.Method;import org.springframework.aop.MethodBeforeAdvice;import org.springframework.aop.framework.ProxyFactory;public class SpringProxyClient { public static void main(String[] args) { ProxyFactory proxy = new ProxyFactory(new SpringPojo()); proxy.addAdvice(new PojoAdvice()); SpringPojo proxyPojo = (SpringPojo) proxy.getProxy(); proxyPojo.foo(); }}class SpringPojo { public void foo() { System.out.println("This is SpringPojo foo"); }}class PojoAdvice implements MethodBeforeAdvice{ @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println("This is bar"); }}
这段代码最重要的一个类是ProxyFactory,此类以及相关的类的类图如下:
如果想要使用AspectJ风格的AOP可以使用AspectJProxyFactory。在使用ProxyFactory生成代理对象的时候,当实例化ProxyFactory对象时就会收集代理目标对象的接口信息,源代码如下:
public ProxyFactory(Object target) { setTarget(target); setInterfaces(ClassUtils.getAllInterfaces(target)); }
代理目标的接口信息存放在类AdvisedSupport的interfaces属性中,此属性是一个集合,如下:
private List<Class<?>> interfaces = new ArrayList<Class<?>>();
当然在实例化ProxyFactory对象之前Spring还会实例化一个更重要的对象:AopProxy对象,此接口才是真正产生代理对象的接口,其实现类有两个:JdkDynamicAopProxy和ObjenesisCglibAopProxy,分别对应JDK动态代理实现和Cglib实现。ProxyFactory的父类ProxyCreatorSupport会保存一个AopProxyFactory类型的属性aopProxyFactory,如下:
private AopProxyFactory aopProxyFactory;
此属性会在ProxyCreatorSupport的无参构造函数中实例化,如下:
/** * Create a new ProxyCreatorSupport instance. */ public ProxyCreatorSupport() { this.aopProxyFactory = new DefaultAopProxyFactory(); }
当调用ProxyFactory的getProxy()方法时首先会调用DefaultAopProxyFactory类的createAopProxy()方法产生一个AopProxy对象,此时就需要判断使用JDK的动态代理还是GCLIB的代理类产生代理对象,在条件允许的情况下Spring会首选JDK动态代理的方式,其判断逻辑为目标对象类型是接口或者其本身就已经是一个JDK动态代理生成的对象。如果不满足上面的条件就使用Cglib代理生成代理对象,其源码如下:
@Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }
AopProxy对象生成后就可以直接调用其getProxy()方法产生代理对象了。AopProxyFactory接口的createAopProxy()方法屏蔽了如何选择以及选择哪种代理,对客户端而言这些都是透明的。