springAOP的注解

来源:互联网 发布:如何分析大数据 编辑:程序博客网 时间:2024/06/05 18:22

前面说到了使用注解的方式把目标类和切面放到spring容器中,那么我们现在使用注解的形式把aop配置到spring容器中。
为了突出区别,我们把前面“springAOP的入门例子“拿出来重构。关于具体的需求以及需求分析,可以查看前面的文章。

spring配置文件:

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:context="http://www.springframework.org/schema/context"    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://www.springframework.org/schema/beans           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd            http://www.springframework.org/schema/context           http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <!--     在这里的scheme约束比例子中多了几行,因为这里要用到类的扫描,也要通过注解的形式把目标类和切面放到spring容器中。  -->            <!--             context:component-scan 扫描相应的包,把目标类和切面放到spring容器中。   -->           <context:component-scan base-package="cn.ansel.spring.aop.annotation.sh"></context:component-scan>           <!--             aop:aspectj-autoproxy 让spring自动产生代理对象,这个标签的作用是aop的注解解析器            -->           <aop:aspectj-autoproxy></aop:aspectj-autoproxy></beans>

person类没有改变,修改一下person的映射文件中Person的引用以及hibernate配置文件中person映射文件的引用。

切面:

/** * Component:代表把这个类放到spring容器中 * @Aspect:相当于spring配置文件中的<aop:config> *  * */@Component("myTransaction")@Aspectpublic class MyTransaction extends hibernateUitls{    private Transaction transaction;    /**     * @Pointcut:放在了方法中,详情看源代码,spring的规定     *           其中一共有2个属性,一个是value,另外一个是arguments     *          这里我们用到的是value,它代表切入点表达式。     *          切入点表达式的写法跟我们在使用xml形式的写法一样。     * private void aa(){}:     *          private:我们把有@Pointcut的方法叫注解方法,这个方法由于不希望被     *                  继承的类使用,所以要用private     *      *          void   :因为这个方法只是做签名方法,所以函数主体中有内容没有什么意义     *                           *          aa()   :相当于配置文件中     *                  <aop:pointcut expression=     *                    "execution(* cn.ansel.spring.aop.annotation.PersonDaoImpl.*(..))"                           id="perform" />                           id的取值。     */    @Pointcut("execution(* cn.ansel.spring.aop.annotation.sh.PersonDaoImpl.*(..))")    private void aa(){}    //代表前置通知    @Before("aa()")    public void beginTransaction(){        transaction=sessionFactory.getCurrentSession().beginTransaction();    }    /**     * 代表后置通知,returning相当于     * <aop:after-returning      *      method="commit"      *      returning="val"/>     * 中的returning     */    @AfterReturning(value="aa()",returning="val")    public void commit(Object val){        System.out.println(val);        transaction.commit();    }}

//把personDaoImpl(目标类)放到spring容器中,并且表明它属于Mvc的持久化层@Repository("personDaoImpl")public class PersonDaoImpl  extends hibernateUitls {    //(目标方法),操作hibernate框架来保存对象,并返回一个字符串    public String savePerson(Person person) {        sessionFactory.getCurrentSession().save(person);        return "helloAOP";    }}

测试类只是把spring配置文件的引用修改了一下。

运行结果:
这里写图片描述

数据库:
这里写图片描述


aop注解的运行流程:

1、由于运行的是测试类,那么首先读取spring的配置文件
2、在配置文件里面读取到了类的扫描器和aop的注解解析器
3、从类的扫描中配置的相应包中扫描,看看哪个类上有component及其子类的注解,扫描到就创建它们的对象
4、读取到aop的注解解析器:<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
这句话时,spring容器再次扫描类扫描器相应包下的类,看看哪个类上面有@aspect注解,然后再查询@pointcut注解在哪里,并且根据里面的切入点表达式寻找相应的目标类,为目标类创建代理对象,然后再读取其中的所有通知,把目标方法跟通知整合。
5、由客户端调用目标方法,然后执行代理方法(目标方法+通知)
6、关闭spring容器

从运行流程可以看出,spring容器要做一层层的扫描,如果相应包中的类很多的话,扫描会降低效率

0 0