Spring的使用(二):AOP

简介

    Aspect Oriented Programming(AOP)称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,如日志,事务,权限等等

相关概念

  1. 满足OCP开闭原则:对程序扩展打开,对程序修改关闭
  2. Aspect(切面):通常是一个类,在切面中定义通知和切入点
  3. JointPoint(连接点):需要拦截的点(方法类型)
  4. PointCut(切入点):指定连接点的规则,规定连接点连接位置以及对连接点进行筛选
  5. Advice(通知):决定增强业务的内容,有before(前置),after(后置),afterReturning(最终),afterThrowing(异常),around(环绕)

搭建

  1. 依赖包 spring-aop
  2. AspectJ组件
    a.aopalliance (aop联盟规则)
    b.spring-aspects(spring的aspectj集成包)
    c.aspectj.weaver(AspectJ织入包)

连接点

自动记录对应方法的信息
方法名:jointPoint.getSignature().getName()
目标对象:jointPoint.getTarget().getClass().getName()
代理对象:jointPoint.getThis().getClass().getName()
方法的返回值(后置通知,环绕通知,最终通知) 要在配置文件中配置返回值绑定到后置通知的参数上

使用

applicationContext.xml

<!--业务层-->
<bean id="userService" class="com.service.UserServiceImpl"></bean>
<bean id="proService" class="com.service.ProServiceImpl"></bean>

<!--切面-->
<bean id="myAspect" class="com.aop.MyAspect"></bean>

<!--配置切入点和切面-->
<aop:config>
    <aop:pointcut id="xxx1" expression="bean(proService)"/>
    <!--1.规定切面  -->
    <aop:aspect ref="myAspect">
        <!--2.切入点 切入的规则-->
        <aop:pointcut id="xxx" expression="bean(*Service)"/>
        <!--3.配置通知的时间点-->
        <!--
            1.前置通知before 在进入连接点之前执行
            2.后置通知AfterReturning 连接点执行之后通知再执行
            3.环绕通知Around 连接点执行的整个过程
            4.异常通知AfterThrowing  在连接点抛出异常之后
            5.最终通知After 无论方法是否异常都一定会执行
        -->
       <aop:before method="beforeLogin" pointcut-ref="xxx" ></aop:before>
       <aop:after-returning method="afterRetuturningLogin" pointcut-ref="xxx" returning="returnVal"></aop:after-returning>
       <aop:around method="around" pointcut-ref="xxx"></aop:around>
       <aop:after-throwing method="afterThrowing" pointcut-ref="xxx" throwing="ex"></aop:after-throwing>
       <aop:after method="after" pointcut="bean(*Service)" ></aop:after>
    </aop:aspect>
</aop:config>

MyAspect.java(切面类)

public class MyAspect {
    //前置通知
    public void beforeLogin(JoinPoint jointPoint){
        //方法名
        System.out.println("=============开始进入前置通知===============");
        System.out.println("拦截的方法名是===" + jointPoint.getSignature().getName());
        System.out.println("目标对象是==="+jointPoint.getTarget().getClass().getName());
        System.out.println("代理对象是====" + jointPoint.getThis().getClass().getName());
        System.out.println("当前方法的参数" + Arrays.toString(jointPoint.getArgs()));
        System.out.println("进入了方法前的时间是" + CommmonUtil.getTime());
        System.out.println("=============前置通知结束===============");
    }

    //后置通知
    public void afterRetuturningLogin(JoinPoint jointPoint,Object returnVal){
        System.out.println("=============开始进入后置通知===============");
        System.out.println("拦截的方法名是===" + jointPoint.getSignature().getName());
        System.out.println("目标对象是==="+jointPoint.getTarget().getClass().getName());
        System.out.println("代理对象是====" + jointPoint.getThis().getClass().getName());
        System.out.println("当前方法的返回值是" + returnVal);
        System.out.println("出方法的时间是" + CommmonUtil.getTime());
        System.out.println("=============后置通知结束===============");
    }
	//环绕通知(本质就是代理原来的方法)
    public Object around(ProceedingJoinPoint jointPoint) throws Throwable {
        System.out.println("=============开始进入环绕通知===============");
        System.out.println("拦截的方法名是===" + jointPoint.getSignature().getName());
        System.out.println("目标对象是==="+jointPoint.getTarget().getClass().getName());
        System.out.println("代理对象是====" + jointPoint.getThis().getClass().getName());
        System.out.println("当前方法的参数" + Arrays.toString(jointPoint.getArgs()));
        System.out.println("进入了方法前的时间是" + CommmonUtil.getTime());
        Object returnVal = jointPoint.proceed();
        System.out.println("当前方法的返回值是" + returnVal);
        System.out.println("出方法的时间是" + CommmonUtil.getTime());
        System.out.println("=============环绕通知结束===============");
        return returnVal;
    }

    //异常通知
    public void afterThrowing(JoinPoint jointPoint,Throwable ex){
        System.out.println("=============开始进入异常通知===============");
        System.out.println("拦截的方法名是===" + jointPoint.getSignature().getName());
        System.out.println("目标对象是==="+jointPoint.getTarget().getClass().getName());
        System.out.println("代理对象是====" + jointPoint.getThis().getClass().getName());
        System.out.println("异常信息为=====" + ex.getMessage());
        System.out.println("异常时间是" + CommmonUtil.getTime());
        System.out.println("=============异常通知结束===============");
    }

    //最终通知
    public void after(JoinPoint jointPoint){
        System.out.println("=============开始进入最终通知===============");
        System.out.println("拦截的方法名是===" + jointPoint.getSignature().getName());
        System.out.println("目标对象是==="+jointPoint.getTarget().getClass().getName());
        System.out.println("代理对象是====" + jointPoint.getThis().getClass().getName());
        System.out.println("最终的时间是" + CommmonUtil.getTime());
        System.out.println("=============最终结束===============");
    }
}

调用*Service实例中的方法则会完成AOP代理运行。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章