AOP又称面向切面编程,可以不变改变原有业务的基础上进行功能的扩展,例如我们声明一个service类来处理servlet传过来的数据,每一次调用service中的验证登录信息方法的时候的都要进行日志的记录,在不改变该验证方法的基础上,我们可以利用AOP思想借助spring的提供的类,进行面向切面编程,将该方法当作切点,配置前置通知和后置通知。
一、需要的包
二、Schema-based实现方式
1、先声明一个类实现接口
- 前置通知实现MethodBeforeAdvice接口(所在包:org.springframework.aop.MethodBeforeAdvice)
- 后置通知实现AfterReturningAdvice接口(所在包:org.springframework.aop.AfterReturningAdvice)
- 实现接口的未实现方法2、实现接口中各方法的参数说明
2、实现接口中未实现的方法进行
public class MyBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
System.out.println("执行前置切面");
}
}
参数说明:
- arg0: 切点方法返回值
- arg1:切点方法对象
- arg2:切点方法参数
- arg3:切点方法所在类的对象
3、applicationContext.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"
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.xsd">
<bean id="mybefor" class="com.hpu.tadvice.MyBeforeAdvice"></bean>
<!-- 通知类 -->
<bean id="demo" class="com.hpu.test.Demo"></bean>
<aop:config>
<aop:pointcut expression="execution(* com.hpu.test.Demo.demo2())" id="mypoint"/>
<aop:advisor advice-ref="mybefor" pointcut-ref="mypoint"/>
</aop:config>
</beans>
- <aop:pointcut expression=“execution(* com.hpu.test.Demo.demo2())” id=“mypoint”/>配置切点
- <aop:advisor advice-ref=“mybefor” pointcut-ref=“mypoint”/>通知类配置
- 注意 * 通配符,匹配任意方法名,任意类名,任意一级包名
- 如果希望匹配任意方法参数 (…)
4、测试代码
package com.hpu.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContextl.xml");
Demo bean = ac.getBean("demo",Demo.class);
bean.demo1();
bean.demo2();
bean.demo3();
}
}
三、AspectJ 方式实现
1、声明一个类不需要实现任何接口,可以在该类中重写前置通知方法或后置通知方法
package com.hpu.tadvice;
import org.aspectj.lang.ProceedingJoinPoint;
public class MyAdvice {
public void mybefore(String name1,int age1){
System.out.println("前置"+name1 );
}
public void mybefore1(String name1){
System.out.println("前置:"+name1);
}
public void myaftering(){
System.out.println("后置 2");
}
public void myafter(){
System.out.println("后置 1");
}
public void mythrow(){
System.out.println("异常");
}
public Object myarround(ProceedingJoinPoint p) throws
Throwable{
System.out.println("执行环绕");
System.out.println("环绕-前置");
Object result = p.proceed();
System.out.println("环绕后置");
return result;
}
}
2、配置applicationContext
<bean id="myadvice" class="com.hpu.tadvice.MyAdvice"></bean>
<aop:config>
<!-- <aop:pointcut expression="execution(* com.hpu.test.Demo.demo2())" id="mypoint"/>
<aop:advisor advice-ref="mybefor" pointcut-ref="mypoint"/> -->
<aop:aspect ref="myadvice">
<aop:pointcut expression="execution(* com.hpu.test.Demo.demo1(String,int)) and args(name1,age1)" id="mypoint"/>
<aop:before method="mybefore" pointcut-ref="mypoint" arg-names="name1,age1"/>
<aop:after method="myafter" pointcut-ref="mypoint" arg-names="name1,age1"/>
</aop:aspect>
</aop:config>
标签解释
<aop:after/> 后置通知,是否出现异常都执行
<aop:after-returing/> 后置通知,只有当切点正确执行时执行
<aop:after/> 和 <aop:after-returing/> 和<aop:after-throwing/>执行顺序和配置顺序有关
execution() 括号不能扩上 args
中间使用 and 不能使用&& 由 spring 把 and 解析成&&
args(名称) 名称自定义的.顺序和 demo1(参数,参数)对应
<aop:before/> arg-names=” 名 称 ” 名 称 来 源 于expression=”” 中 args(),名称必须一样
args() 有几个参数,arg-names 里面必须有几个参数
arg-names=”” 里面名称必须和通知方法参数名对应
四、环绕通知
1、声明一个类实现MethodInterceptor接口
public class MyArround implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation arg0) throws Throwable {
System.out.println("环绕-前置");
Object result = arg0.proceed();//放行,调用切点方式
System.out.println("环绕-后置");
return result;
}
}
2、applicationContext.xml
<bean id="myarround" class="com.bjsxt.advice.MyArround"></bean>
<aop:config>
<aop:pointcut expression="execution(*com.bjsxt.test.Demo.demo1())" id="mypoint"/>
<aop:advisor advice-ref="myarround" pointcut-ref="mypoint" />
</aop:config>
<bean id="demo" class="com.bjsxt.test.Demo"></bean>