,好记性不如烂笔头


基于XML配置方式声明切面

Spring使用org.springframework.aop.Advisor接口表示切面的概念,Advisor表示只有一个通知(org.aopalliance.aop.Advice)和一个切入点(org.springframework.aop.Pointcut)的切面。Advisor可以使用<aop:config>标签下的<aop:advisor>标签定义。

    pointcut和pointcut-ref:二者选一,指定切入点表达式;

    advice-ref:引用通知API实现Bean,如前置通知接口为MethodBeforeAdvice;

Spring配置文件(spring-context-aop-advisor.xml)

    
    
        
    
    
    
    
        
    
        
        
        
        
        
        
        
    

实现类

package com.invicme.apps.aop.advisor;import org.apache.log4j.Logger;import com.invicme.apps.aop.ArithmeticCalculate;/** *  * @author lucl *  * 数学计算实现类 * */public class ArithmeticCalculateImpl implements ArithmeticCalculate {        private static final Logger logger = Logger.getLogger(ArithmeticCalculateImpl.class);        private int i = 0;    private int j = 0;        public ArithmeticCalculateImpl () {        this(0, 0);    }        public ArithmeticCalculateImpl (int i, int j) {        this.i = i;        this.j = j;    }        @Override    public int add(int i, int j) {        logger.info("The method add was invoke with args [" + i + ", " + j + "]");        int sum = i + j;        logger.info("The method add ends with result [" + sum + "]");        return sum;    }    @Override    public int div(int i, int j) {        logger.info("The method div was invoke with args [" + i + ", " + j + "]");        int result = i / j;        logger.info("The method div ends with result [" + result + "]");        return result;    }    @Override    public String validateNum(String level, int i) {        logger.info("The method validateNum was invoke with args [" + level + ", " + i + "]");        String result = this.getMsg(i);        logger.info("The method validateNum ends with result [" + result + "]");        return result;    }    private String getMsg (int i) {        if (i > 0) {            return "正数";        }        return "负数";    }}

前置通知

package com.invicme.apps.aop.advisor;import java.lang.reflect.Method;import java.util.Arrays;import org.apache.log4j.Logger;import org.springframework.aop.MethodBeforeAdvice;/** *  * @author lucl *  * 前置通知(Adivisor是一种特殊的Aspect,Advisor代表spring中的Aspect ) *  */public class BeforeAdviceLogAdapter implements MethodBeforeAdvice {    private static final Logger logger = Logger.getLogger(BeforeAdviceLogAdapter.class);         /**     * 前置通知,在目标方法执行之前被调用(JoinPoint参数不是必须的,传入是为了获取目标对象的相关属性)     */    public void before(Method method, Object[] args, Object target) throws Throwable {        /**         * target.getClass().getName() : 获取的是全路径名(包名+类名)         * target.getClass().getSimpleName() : 获取类名         */        String className = target.getClass().getSimpleName();        logger.info("[
]" + className + "@" + method.getName() + " was invoke with args " + Arrays.asList(args) + ".");    }}

后置通知

package com.invicme.apps.aop.advisor;import java.lang.reflect.Method;import java.util.Arrays;import org.apache.log4j.Logger;import org.springframework.aop.AfterReturningAdvice;/** *  * @author lucl *  * 后置通知 */public class AfterReturningAdviceLogAdapter implements AfterReturningAdvice {    private static final Logger logger = Logger.getLogger(AfterReturningAdviceLogAdapter.class);         @Override    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {        String className = target.getClass().getSimpleName();        logger.info("[
]" + className + "@" + method.getName() + " args " + Arrays.asList(args) + ", result " + returnValue + ".");    }}

异常通知

package com.invicme.apps.aop.advisor;import java.lang.reflect.Method;import java.util.Arrays;import org.apache.log4j.Logger;import org.springframework.aop.ThrowsAdvice;/** *  * @author lucl *  * 异常通知 *  * 
 * There are not any methods on this interface, as methods are invoked by reflection.  * Implementing classes must implement methods of the form:  *  *     void afterThrowing([Method, args, target], ThrowableSubclass); *     Some examples of valid methods would be:  *      *     public void afterThrowing(Exception ex) *     public void afterThrowing(RemoteException) *     public void afterThrowing(Method method, Object[] args, Object target, Exception ex) *     public void afterThrowing(Method method, Object[] args, Object target, ServletException ex) * 
 */public class ThrowAdviceLogAdapter implements ThrowsAdvice {    private static final Logger logger = Logger.getLogger(ThrowAdviceLogAdapter.class);        /**     *      * @param method     * @param args     * @param target     * @param ex     */    public void afterThrowing(Method method, Object[] args, Object target, Exception ex) {        String className = target.getClass().getSimpleName();        logger.info("[
]" + className + "@" + method.getName() + " args " + Arrays.asList(args) + " occurs exception : " + ex + ".");    }}

环绕通知

package com.invicme.apps.aop.advisor;import java.lang.reflect.Method;import java.util.Arrays;import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;import org.apache.log4j.Logger;/** *  * @author 环绕通知 * */public class AroundInterceptorLogAdapter implements MethodInterceptor {    private static final Logger logger = Logger.getLogger(AroundInterceptorLogAdapter.class);    @Override    public Object invoke(MethodInvocation invocation) throws Throwable {        // 参数        Object [] args = invocation.getArguments();        // 目标方法        Method method = invocation.getMethod();                Object result = null;                try {            // before advise            logger.info("[
]" + method.getName() + " was invoke with args " + Arrays.asList(args) + ".");            result = invocation.proceed();        } catch (Exception ex) {            // throw advise            logger.info("[
]" + method.getName() + " occrus error " + ex + ".");        }                // after running advise        logger.info("[
]" + method.getName() + " ends with result " + result + ".");        return result;    }}

单元测试类

package com.test.apps.spring.aop;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.invicme.apps.aop.ArithmeticCalculate;/** *  * @author lucl * */public class TestSpringAopOfAdvisor {    @Test    public void testSpringAopOfAdvisor () {        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/spring-context-aop-advisor.xml");        ArithmeticCalculate calculate = context.getBean("calculate", ArithmeticCalculate.class);        calculate.add(1, 2);        System.out.println("----------------------------------------------------------------");        try {            Thread.sleep(1 * 1000);        } catch (InterruptedException e) {            e.printStackTrace();        }        calculate.div(1, 0);    }}

执行结果

不推荐使用Advisor,除非在进行事务控制的情况下,其他情况一般不推荐使用该方式,该方式属于侵入式设计,必须实现通知API。