springAOP的注解

前面说到了使用注解的方式把目标类和切面放到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")
@Aspect
public 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值