Spring AOP 方式一 ProxyFactoryBean

先看例子

<bean id="personTarget" class="com.mycompany.PersonImpl">
    <property name="name" value="Tony"/>
    <property name="age" value="51"/>
</bean>

<bean id="myAdvisor" class="com.mycompany.MyAdvisor">
    <property name="someProperty" value="Custom string property value"/>
</bean>

<bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor">
</bean>

<bean id="person"
    class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="proxyInterfaces" value="com.mycompany.Person"/>

    <property name="target" ref="personTarget"/>
    <property name="interceptorNames">
        <list>
            <value>myAdvisor</value>
            <value>debugInterceptor</value>
        </list>
    </property>
</bean>

 

配置点:

1、interceptorNames    拦截器数组

2、targetName   目标类

3、singleton   是否单例,默认true

4、proxyInterfaces  代理接口

5、optimize   建议使用cglib

6、proxyTargetClass 

 

问题:

1、如何判断是使用jdk代理还是使用CGLIB?

  答:默认使用jdk,如果没有使用接口或optimize 为true或proxyTargetClass 为true

2、为什么interceptorNames可以是什么类型?

     答:可以是Advisor 或 MethodInterceptor 或MethodBeforeAdvice 或 AfterReturningAdvice 或 ThrowsAdvice 的实现类,Spring会自动把以上类封装成Advisor

 

实现原理:

ProxyFactoryBean是FactoryBean的实现类,其接口getObject会返回一个代理对象;如果代理方式为JDK,那么获取对象将返回一个JDK的代理对象,执行方式时将执行继承InvocationHandler的invoke方法

JdkDynamicAopProxy.invoke方法流程如下

1、如果方法是equals或hashCode 会特殊处理,暂不将

2、如果方式是继承自Advice,将直接执行

3、然后以递归的方式执行各个拦截器

 

MethodBeforeAdviceInterceptor 执行如下

public Object invoke(MethodInvocation mi) throws Throwable {
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
        return mi.proceed();
    }
AfterReturningAdviceInterceptor 执行如下

public Object invoke(MethodInvocation mi) throws Throwable {
        Object retVal = mi.proceed();
        this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
        return retVal;
    }
ThrowsAdviceInterceptor 执行如下

public Object invoke(MethodInvocation mi) throws Throwable {
        try {
            return mi.proceed();
        }
        catch (Throwable ex) {
            Method handlerMethod = getExceptionHandler(ex);
            if (handlerMethod != null) {
                invokeHandlerMethod(mi, ex, handlerMethod);
            }
            throw ex;
        }
    }
/**
     * Determine the exception handle method. Can return null if not found.
     * @param exception the exception thrown
     * @return a handler for the given exception type
     */
    private Method getExceptionHandler(Throwable exception) {
        Class exceptionClass = exception.getClass();
        if (logger.isTraceEnabled()) {
            logger.trace("Trying to find handler for exception of type [" + exceptionClass.getName() + "]");
        }
        Method handler = this.exceptionHandlerMap.get(exceptionClass);
        while (handler == null && !exceptionClass.equals(Throwable.class)) {
            exceptionClass = exceptionClass.getSuperclass();
            handler = this.exceptionHandlerMap.get(exceptionClass);
        }
        if (handler != null && logger.isDebugEnabled()) {
            logger.debug("Found handler for exception of type [" + exceptionClass.getName() + "]: " + handler);
        }
        return handler;
    }
private void invokeHandlerMethod(MethodInvocation mi, Throwable ex, Method method) throws Throwable {
        Object[] handlerArgs;
        if (method.getParameterTypes().length == 1) {
            handlerArgs = new Object[] { ex };
        }
        else {
            handlerArgs = new Object[] {mi.getMethod(), mi.getArguments(), mi.getThis(), ex};
        }
        try {
            method.invoke(this.throwsAdvice, handlerArgs);
        }
        catch (InvocationTargetException targetEx) {
            throw targetEx.getTargetException();
        }
    }

 

 

posted @ 2013-11-08 18:08  benx621  阅读(515)  评论(0编辑  收藏  举报