用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容器管理
需要注意切入点执行的方法的参数