基于XML配置的Sping AOP详解
一、编写基本处理方法
package com.kang.sping.xml.aop; public class Math{ //加 public int add(int n1,int n2){ int result=n1+n2; System.out.println(n1+"+"+n2+"="+result); return result; } //减 public int sub(int n1,int n2){ int result=n1-n2; System.out.println(n1+"-"+n2+"="+result); return result; } //乘 public int mut(int n1,int n2){ int result=n1*n2; System.out.println(n1+"*"+n2+"="+result); return result; } //除 public int div(int n1,int n2){ int result=n1/n2; System.out.println(n1+"/"+n2+"="+result); return result; } }
二、编写通知类
package com.kang.sping.xml.aop; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; /** * 通知类,横切逻辑 * */ public class Advices { public void before(JoinPoint jp){ System.out.println("----------前置通知----------"); System.out.println(jp.getSignature().getName()); } public void after(JoinPoint jp){ System.out.println("----------最终通知----------"); } public void afterReturning(JoinPoint joinPoint, Object result){ //定义AfterReturning通知方法 } public void afterThrowing(JoinPoint joinPoint, Exception e){ //定义AfterThrowing通知方法 } public Object around(ProceedingJoinPoint pjd){ //定义Around通知方法 return null; } }
三、配置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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 被代理的对象 --> <bean id="math" class="com.kang.sping.xml.aop.Math"></bean> <!-- 配置切面的 bean.切面 Bean 必须有一个标示符id, 供 <aop:aspect> 元素引用 --> <bean id="advices" class="com.kang.sping.xml.aop.Advices"></bean> <!-- 可以定义多个切面bean,例如再定义一个日志bean --> <!-- <bean id="loggingAspect" class="com.kang.spring.xml.aop.LoggingAspect"></bean> --> <!-- aop配置 --> <!-- proxy-target-class属性值决定是基于接口的还是基于类的代理被创建。 如果proxy-target-class 属性值被设置为true,那么基于类的代理将起作用(这时需要cglib库)。 如果proxy-target-class属值被设置为false或者这个属性被省略,那么标准的JDK 基于接口的代理。 spring使用aop时需要设置proxy-target-class="true" ,否则无法依赖注入 --> <!-- 所有的 Spring AOP 配置都必须定义在 <aop:config> 元素内部 --> <aop:config proxy-target-class="true"> <!-- 配置切点表达式,id标示了该切点以供下面引用。切入点必须定义在 <aop:aspect> 元素下, 或者直接定义在 <aop:config>元素下. 定义在 <aop:aspect> 元素下: 只对当前切面有效。 定义在 <aop:config> 元素下: 对所有切面都有效。 基于 XML的 AOP 配置不允许在切入点表达式中用名称引用其他切入点. --> <aop:pointcut expression="execution(* com.kang.sping.xml.aop.Math.*(..))" id="pointcut1" /> <!-- 配置切面 .每个切面而言, 都要创建一个 <aop:aspect> 元素来为具体的切面实现, 用以引用具体bean的方法 这里配置为ref="advices",则可以调用advices对应的类中的方法 --> <aop:aspect ref="advices"> <!--配置连接通知方法与切点,method 属性指定切面类中通知方法的名称 --> <aop:before method="before" pointcut-ref="pointcut1" /> <aop:after method="after" pointcut-ref="pointcut1" /> <!-- 配置其他通知方法 <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut1" throwing="e"/> <aop:after-returning method="afterReturning" pointcut-ref="pointcut1" returning="result"/> <aop:around method="around" pointcut-ref="pointcut1"/> --> </aop:aspect> <!--aspect里面有一个order属性,order属性的数字就是横切关注点的优先级顺序 --> <!-- 可以配置多个切面 <aop:aspect ref="loggingAspect" order="1"> <aop:before method="doLogging" pointcut-ref="pointcut1" /> </aop:aspect> --> </aop:config> </beans>
package com.kang.sping.xml.aop; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-xml.xml"); Math math = ctx.getBean("math", Math.class); int n1 = 100, n2 = 5; math.add(n1, n2); math.sub(n1, n2); math.mut(n1, n2); math.div(n1, n2); } }
五、运行结果
六、总结
正常情况下, 基于注解的声明要优先于基于 XML 的声明. 通过 AspectJ 注解, 切面可以与 AspectJ 兼容, 而基于 XML 的配置则是 Spring 专有的. 由于 AspectJ 得到越来越多的 AOP 框架支持, 所以以注解风格编写的切面将会有更多重用的机会。当使用 XML 声明切面时, 需要在 <beans> 根元素中导入 aop Schema命名空间。