從零開始造Spring09---實現(xiàn)AOP的JDK代理

前言

接上一篇從零開始造Spring08—AOP(介紹以及實現(xiàn)ReflectiveMethodInvocation和AopProxyFactory),這篇文章我們接著來講Spring的AOP的JDK代理,這是學(xué)習(xí)劉欣老師的《從零開始造Spring》的學(xué)習(xí)筆記。

JDK代理的說明

與Cglib代理有所不同的是,JDK代理是針對接口的代理。所有要使用JDK代理必須要有接口。

測試類

public interface IPetStoreService {
    void placeOrder();
}
@Component(value = "petStoreService")
public class PetStoreService implements IPetStoreService {
    public PetStoreService() {
    }

    @Override
    public void placeOrder() {
        System.out.println("place order");
        MessageTracker.addMsg("place order");
    }
}

XML中的配置

        <context:component-scan
        base-package="com.jay.spring.service.v6">
    </context:component-scan>

    <!--作為一個切面-->
    <bean id="tx" class="com.jay.spring.tx.TransactionManager" />

    <aop:config>

        <aop:aspect ref="tx">
            <!--切點-->
            <aop:pointcut id="placeOrder"
                expression="execution(* com.jay.spring.service.v6.*.placeOrder(..))" />
            <aop:after-throwing pointcut-ref="placeOrder" method = "rollback"/>
            <aop:after-returning pointcut-ref="placeOrder"
                method="commit" />

            <aop:before pointcut-ref="placeOrder" method="start" />         
        </aop:aspect>
    </aop:config>

JdkAopProxyFactory

public class JdkAopProxyFactory implements AopProxyFactory,InvocationHandler {
    private static final Log logger = LogFactory.getLog(JdkAopProxyFactory.class);

    private final AopConfig aopConfig;

    public JdkAopProxyFactory(AopConfig config) {
        Assert.notNull(config, "AdvisedSupport must not be null");
        if (config.getAdvices().size() == 0) {
            throw new AopConfigException("No advice specified");
        }
        this.aopConfig = config;
    }

    /**
     * 獲取代理
     * @return
     */
    @Override
    public Object getProxy() {
        return getProxy(ClassUtils.getDefaultClassLoader());
    }

    @Override
    public Object getProxy(ClassLoader classLoader) {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating JDK dynamic proxy: target source is " + this.aopConfig.getTargetObject());
        }
        Class<?>[] proxiedInterfaces = aopConfig.getProxiedInterfaces();
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//        獲取目標對象
        Object target = this.aopConfig.getTargetObject();
        Object retVal;

        // Get the interception chain for this method.
        //獲取通知點
        List<Advice> chain = this.aopConfig.getAdvices(method);
        // Check whether we have any advice. If we don't, we can fallback on direct
        // reflective invocation of the target, and avoid creating a MethodInvocation.
        if (chain.isEmpty()) {
            // We can skip creating a MethodInvocation: just invoke the target directly
            // Note that the final invoker must be an InvokerInterceptor so we know it does
            // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
            retVal = method.invoke(target, args);
        } else {
            List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>();
            interceptors.addAll(chain);


            // We need to create a method invocation...
            retVal = new ReflectiveMethodInvocation(target, method, args, interceptors).proceed();


        }
        // Massage return value if necessary.
        /*Class<?> returnType = method.getReturnType();
        if (retVal != null && retVal == target && returnType.isInstance(proxy) ) {
            // Special case: it returned "this" and the return type of the method
            // is type-compatible. Note that we can't help if the target sets
            // a reference to itself in another returned object.
            retVal = proxy;
        }
        else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
            throw new AopInvocationException(
                    "Null return value from advice does not match primitive return type for: " + method);
        }*/

        return retVal;
    }
}

說明 JDK代理類必須要實現(xiàn)InvocationHandler 接口。
調(diào)用JDK代理的方法在AspectJAutoProxyCreator

protected Object createProxy(List<Advice> advices, Object bean) {
        AopConfigSupport config = new AopConfigSupport();
        for (Advice advice : advices) {
            config.addAdvice(advice);
        }
        Set<Class> targetInterfaces = ClassUtils.getAllInterfacesForClassAsSet(bean.getClass());
        for (Class<?> targetInterface : targetInterfaces) {
            config.addInterface(targetInterface);
        }
        config.setTargetObject(bean);

        AopProxyFactory proxyFactory = null;
        if (config.getProxiedInterfaces().length == 0) {
            proxyFactory = new CglibProxyFactory(config);
        } else {
            //需要實現(xiàn)JDK代理,有接口的情況下
            proxyFactory=new JdkAopProxyFactory(config);
        }
        return proxyFactory.getProxy();
    }

源碼地址




作者:碼農(nóng)飛哥

微信公眾號:碼農(nóng)飛哥