码迷,mamicode.com
首页 > 编程语言 > 详细

Spring学习笔记AOP(四)

时间:2016-07-13 23:38:37      阅读:280      评论:0      收藏:0      [点我收藏+]

标签:aop:advisor

鲁春利的工作笔记,好记性不如烂笔头



基于XML配置方式声明切面


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


<aop:advisor id="标识" order="执行顺序" 
            pointcut="切入点表达式" pointcut-ref="切入点Bean引用" 
            advice-ref="通知API实现引用" />

    pointcut和pointcut-ref:二者选一,指定切入点表达式;
    advice-ref:引用通知API实现Bean,如前置通知接口为MethodBeforeAdvice;


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

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 业务类 -->
    <bean id="calculate" class="com.invicme.apps.aop.advisor.ArithmeticCalculateImpl" />
    
    <!-- 切入的日志类 -->
    <bean id="beforeAdviceLogAdapter" class="com.invicme.apps.aop.advisor.BeforeAdviceLogAdapter" />
    <bean id="afterAdviceLogAdapter" class="com.invicme.apps.aop.advisor.AfterReturningAdviceLogAdapter" />
    <bean id="throwAdviceLogAdapter" class="com.invicme.apps.aop.advisor.ThrowAdviceLogAdapter" />
    <bean id="aroundAdviceLogAdapter" class="com.invicme.apps.aop.advisor.AroundInterceptorLogAdapter" />
    
    <!-- 
        proxy-target-class 
            true : 表示声明的切面使用CGLib动态代理技术;
            false : 默认值,使用JDK动态代理技术。
        一个配置文件可以有多个<aop:config>,不同的<aop:config>采用不同的代理技术。
    -->
    <aop:config proxy-target-class="false">
        <!-- 声明一个切点 -->
        <aop:pointcut id="logPointcut" expression="execution(public * com.invicme.apps.aop.advisor.ArithmeticCalculateImpl.*(..))"/>
        <!-- advisor只持有一个Pointcut和一个advice,而aspect可以多个pointcut和多个advice -->
        <aop:advisor advice-ref="beforeAdviceLogAdapter" pointcut-ref="logPointcut" />
        <aop:advisor advice-ref="afterAdviceLogAdapter" pointcut-ref="logPointcut" />
        <aop:advisor advice-ref="throwAdviceLogAdapter" pointcut-ref="logPointcut"/>
        <aop:advisor advice-ref="aroundAdviceLogAdapter" pointcut-ref="logPointcut"/>
    </aop:config>
</beans>

实现类

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("[<aop:before>]" + 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("[<aop:after-returning>]" + 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
 * 
 * 异常通知
 * 
 * <pre>
 * 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)
 * </pre>
 */
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("[<aop:after-throwing>]" + 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("[<aop:aroud>]" + method.getName() + " was invoke with args " + Arrays.asList(args) + ".");
            result = invocation.proceed();
        } catch (Exception ex) {
            // throw advise
            logger.info("[<aop:aroud>]" + method.getName() + " occrus error " + ex + ".");
        }
        
        // after running advise
        logger.info("[<aop:aroud>]" + 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。

本文出自 “闷葫芦的世界” 博客,请务必保留此出处http://luchunli.blog.51cto.com/2368057/1826092

Spring学习笔记AOP(四)

标签:aop:advisor

原文地址:http://luchunli.blog.51cto.com/2368057/1826092

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!