标签: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
标签:aop:advisor
原文地址:http://luchunli.blog.51cto.com/2368057/1826092