spring AOP通知类型 及 切入点表达式

版权声明:本文为博主原创文章,转载请标明出处。 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(..)           说明参数为任意类型     返回值为 任意类型且它的子类也会被织入

猜你喜欢

转载自blog.csdn.net/weixin_43014205/article/details/86539232