用spring实现AOP有两种方式:基于xml配置方式和基于注解方式,
基于注解方式
一、架包:cglib-nodep-2.1_3.jar aspectjweaver.jar aspectjrt.jar(AOP)
其它架包:common-annotations.jar spring.jar commons-logging.jar
二、先在配置文件中加入如下内容
<?xml version="1.0" encoding="UTF-8"?> xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> </beans>
三、启动对 aspectj 的支持,在xml文件中加入如下内容
<aop:aspectj-autoproxy />
四、编写核心代码
PersonService.java
package com.qh.service; public interface PersonService { public void save(String name); public void update(String name); }
PersonServiceImp.java
package com.qh.serviceImp; import com.qh.service.PersonService; public class PersonServiceImp implements PersonService { public void save(String name) { System.out.println("我是save()方法!"+name); } public void update(String name) { System.out.println("我是update()方法!"); } }
MyInterceptor.java
package com.qh.service; /* * 切面的实现 */ import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; //指明该类为一个切面 @Aspect public class MyInterceptor { /*定义切入点,拦截方法 *使用AOP表述是语言:执行(返回值类型 要拦截的包 子包 类.方法(任意参数)) *该句解释:执行 com.qh.service及其子包中的所有类的所有带任意参数的方法,并返回任意类型值 */ @Pointcut("execution(* com.qh.service..*.*(..))") private void anyMethod(){}//声明一个切入点名称anyMethod() @Before("anyMethod()")//定义前置通知,当然还有其它通知 public void doprint(){ System.out.println("执行!"); } }
//其它通知 //只拦截包含一个参数的方法,并将该参数传给doBefore()方法 @Before("anyMethod()&&args(str)") public void doBefore(String str){ System.out.println("我是前置通知!"+str); } //定义后置通知,将拦截的方法的返回结果作为doAfterReturning()方法的参数 @AfterReturning(pointcut="anyMethod()",returning="str") public void doAfterReturning(String str){ System.out.println("我是后置通知!"+str); } //定义例外通知,将异常信息作为doAfterThrowing()方法的参数 @AfterThrowing(pointcut="anyMethod()",throwing="e") public void doAfterThrowing(Exception e){ System.out.println("我是例外通知!"+e); } @After("anyMethod()")//定义最终通知 public void doAfter(){ System.out.println("我是最终通知!"); } @Around("anyMethod()")//定义环绕通知,此方法适合做权限控制 //此方法格式固定 public Object doAround(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("我是环绕通知!进入方法"); //if(){ Object object=pjp.proceed();//一定要执行的方法,假如不执行该方法,被拦截的方法是不会执行的 //} System.out.println("我是环绕通知!退出方法"); return object; }
五、将PersonServiceImp和MyInterceptor类交给spring容器
<bean id="personServiceImp" class="com.qh.serviceImp.PersonServiceImp"></bean> <bean id="myInterceptor" class="com.qh.service.MyInterceptor"></bean>
六、编写测试代码:InterceptorTest.java
package com.qh.test; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.qh.service.PersonService; public class InterceptorTest { @Test public void test() { ApplicationContext apx=new ClassPathXmlApplicationContext("beans.xml"); PersonService personService=(PersonService) apx.getBean("personServiceImp"); personService.save("xionggui"); } }
七、结果
执行!
我是save()方法!xionggui
八、小结(针对本例)
例外通知出现在Junit的控制台中、环绕通知多用于权限控制
基于xml配置方式
一、架包和第一种方式一样
二、xml文件
<aop:config><!-- aop配置 --> <aop:aspect id="aopCut" ref="myInterceptor"><!-- 引用切面 --> <!-- 可以定义多个切入点 --> <aop:pointcut expression="execution(* com.qh.service..*.*(..)) and args(str)" id="myPointcut"/> <aop:pointcut expression="execution(* com.qh.service..*.*(..))" id="myPointcut2"/> <aop:before method="doBeforeOne" pointcut-ref="myPointcut2" /> <aop:before method="doBefore" pointcut-ref="myPointcut" arg-names="str"/> <aop:after-returning method="doAfterReturning" pointcut-ref="myPointcut" arg-names="str"/> <!-- aop:after-throwing method="doAfterThrowing" pointcut-ref="myPointcut"/--> <aop:after method="doAfter" pointcut-ref="myPointcut2"/> <aop:around method="doAround" pointcut-ref="myPointcut2"/> </aop:aspect> </aop:config>
三、PersonServiceImp.java
package com.qh.service; /* * 切面的实现 */ import org.aspectj.lang.ProceedingJoinPoint; public class MyInterceptor { public void doBeforeOne(){ System.out.println("我是第一个前置通知!"); } public void doBefore(String str){ System.out.println("我是前置通知!"+str); } public void doAfterReturning(String str){ System.out.println("我是后置通知!"+str); } public void doAfterThrowing(Exception e){ System.out.println("我是例外通知!"+e); } public void doAfter(){ System.out.println("我是最终通知!"); } public Object doAround(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("我是环绕通知!进入方法"); //if(){ Object object=pjp.proceed();//一定要执行的方法,假如不执行该方法,被拦截的方法是不会执行的 //} System.out.println("我是环绕通知!退出方法"); return object; } }
其它代码和第一种方法一样。
四、注意
要将上面2个类交给spring容器管理
需要注意切入点执行的方法的参数