版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/weixin_43014205/article/details/86539232
通知类型
前置通知 在目标方法执行之前进行操作
实现类:
public class GoodsDaoImpl implements GoodsDao {
@Override
public void save() {
System.out.println("保存操作");
}
@Override
public void update() {
System.out.println("更新");
}
}
切面类:
public class MyAspect {
public void check(){
System.out.println("权限校验");
}
}
配置文件:
<?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="goodsDao" class="com.itlike.demo1.GoodsDaoImpl"></bean>
<bean id="myAspect" class="com.itlike.demo2.MyAspect"/>
<!--配置AOP-->
<aop:config>
<!--配置切点 给哪个方法增强-->
<aop:pointcut id="savepoint"
expression="execution(* com.itlike.demo1.GoodsDaoImpl.save(..))"/>
<!--配置切面 增强的方法是什么-->
<aop:aspect ref="myAspect">
<aop:before method="check" pointcut-ref="savepoint"/>
</aop:aspect>
</aop:config>
</beans>
后置通知 在目标方法执行之前进行操作 可以接受切入点的返回值
例如:要在更新之后加上日志功能,
实现类:
public class GoodsDaoImpl implements GoodsDao {
@Override
public String update() {
System.out.println("更新");
return "update----success";
}
}
切面:
public void log(Object res){
System.out.println("日志记录");
}
配置文件:
<!--后置通知-->
<aop:config>
<aop:pointcut id="updatepoint"
expression="execution(* com.itlike.demo1.GoodsDaoImpl.update(..))"/>
<!--切面-->
<aop:aspect ref="myAspect">
<aop:after-returning method="log" pointcut-ref="updatepoint" returning="res"/>
</aop:aspect>
</aop:config>
注意:后置通知可以接受切入点的返回值,可以在配置文件中进行配置 returning=“ xxx” xxx必须和切面中传入的形参必须一致才能接受得到
测试类:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AopTest {
@Resource(name = "goodsDao")
private GoodsDao goodsDao;
@Test
public void test1(){
String update = goodsDao.update();
System.out.println(update);
}
}
环绕通知 在目标方法执行之前和执行之后操作 可以阻止原方法的执行
例如:要对某一方法开启事务,即执行之前开启事务,执行之后提交事务
实现类:
public class GoodsDaoImpl implements GoodsDao {
@Override
public void delete() {
System.out.println("删除操作");
}
}
切面:
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("开启事务");
Object proceed = joinPoint.proceed();
System.out.println("提交事务");
return proceed ;
}
注意:对于环绕通知,必须要有返回值且要传入值,如果要执行原方法,如代码所示,如果要组织原方法的发生,则不调用
Object proceed = joinPoint.proceed(); 返回joinPoint即可
配置文件:
<aop:config>
<aop:pointcut id="deletepoint" expression="execution(* com.itlike.demo1.GoodsDaoImpl.delete(..))"/>
<aop:aspect ref="myAspect">
<aop:around method="around" pointcut-ref="deletepoint"></aop:around>
</aop:aspect>
</aop:config>
异常通知 只有当切入点的方法发生异常时 才会织入切面的方法 并且能够拿到抛出的异常
实现类: 这时的切入点并没有发生异常
public class GoodsDaoImpl implements GoodsDao {
@Override
public void find() {
System.out.println("find");
}
}
切面类:
public void exceptionM(Exception res){
System.out.println("有异常,异常类型为:"+res.getMessage());
}
配置文件:
<!--异常通知-->
<aop:config>
<aop:pointcut id="findpoint" expression="execution(* com.itlike.demo1.GoodsDaoImpl.find(..))"/>
<aop:aspect ref="myAspect">
<aop:after-throwing method="exceptionM" pointcut-ref="findpoint" throwing="res"/>
</aop:aspect>
</aop:config>
同样,returning=“ xxx” xxx必须和切面中传入的形参必须一致才能接受得到
测试类及结果: 切入点没有异常 则切面中的方法不会被织入
goodsDao.find();
//find
假如切入点发生异常
public class GoodsDaoImpl implements GoodsDao {
@Override
public void find() {
System.out.println("find");
int i = 1 / 0;
}
}
再看测试结果:
find
有异常,异常类型为:/ by zero
最终通知 无论代码是否有异常 都会执行
实现类:
public class GoodsDaoImpl implements GoodsDao {
@Override
public void find() {
System.out.println("find");
}
}
切面类:
public class MyAspect {
public void after(){
System.out.println("after");
}
}
配置文件
<!--最终通知-->
<aop:config>
<aop:pointcut id="findpoint" expression="execution(* com.itlike.demo1.GoodsDaoImpl.find(..))"/>
<aop:aspect ref="myAspect">
<aop:after method="after" pointcut-ref="findpoint"/>
</aop:aspect>
</aop:config>
无论实现类中的代码是否发生异常,切面中配置的类都会织入
切入点表达式
都是基于 execution 函数完成的
public com.bullet.demo1.GoodsDaoImpl.save(..) ..说明参数为任意类型
* com.bullet.dem1.GoodsDaoImpl.save(..) 说明参数为任意类型 返回值为 任意类型
* com.bullet.demo1.GoodsDaoImpl+ .save(..) 说明参数为任意类型 返回值为 任意类型且它的子类也会被织入