Spring AOP学习

作者: jwfy | 来源:发表于2018-02-05 13:55 被阅读9次

    AOP 概念了解

    AOP(Aspect Oriented Programming)面向切面编程,是针对面向对象编程的一种补充,同时也是spring中第二个最核心的功能,例如可以进行权限认证,日志输出等,可以无侵入的对原来的功能进行切面加入自定义的非业务功能。

    • 切面(AspectJ):对横切关注点的抽象
    • 连接点(Joinpoint):被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器
    • 通知(Advice):AOP框架在特定的切入点执行的增强处理,分为前置、后置、异常、最终、环绕五种情况
    • 切入点(Pointcut):需要拦截的点
    • 引入:将方法或字段添加到被处理的类中。Spring允许引入新的接口到任何被处理的对象。例如,你可以使用一个引入,使任何对象实现IsModified接口,以此来简化缓存
    • 目标对象:被AOP框架进行增强处理的对象,也被称为被增强的对象
    • AOP代理:AOP框架创建的对象,简单的说,代理就是对目标对象的加强。Spring中的AOP代理可以是JDK动态代理,也可以是CGLIB代理
    • 织入(Weaving):将增强处理添加到目标对象中,并创建一个被增强的对象的过程。

    在spring中AOP代理对象依旧是由IOC容器管理着,在具体代理生成中可以由java动态代理生成也可以由cglib字节码增强完成,具体运行中会根据具体情况选择合适的代码生成方式。如果是接口,则只会使用动态代理生成
    在了解完AOP的基础知识后,介绍AOP的两种使用方法,XML配置和注解

    XML 配置

    <bean id="people" class="com.demo.Aop.People" />
    <bean id="peopleAop" class="com.demo.Aop.PeopleAop" />
    
    <aop:config>
       <aop:pointcut id="pc" expression="execution(* com.demo.Aop.*.*(..))" />
       <aop:aspect ref="peopleAop">
           <aop:after method="after" pointcut-ref="pc" />
           <aop:before method="before" pointcut-ref="pc" />
           <aop:around method="around" pointcut-ref="pc" />
           <aop:after-returning method="afterReturn" pointcut-ref="pc" />
           <aop:after-throwing method="excep" pointcut-ref="pc" />
       </aop:aspect>
    </aop:config>
    
    public class PeopleAop {
    
        public void before(){
            System.out.println("before");
        }
    
        public void after(){
            System.out.println("after");
        }
    
        public Object around(ProceedingJoinPoint pj){
    
            System.out.println("around before");
            Object obj = null;
            try {
                obj = pj.proceed();
            } catch (Throwable throwable) {
    
            }
            System.out.println("around after");
            return obj;
        }
    
        public void afterReturn(){
            System.out.println("after return");
        }
    
        public void excep(){
            System.out.println("error!!!!");
        }
    
    }
    
    public class People {
        public void say() {
            System.out.println("chinese");
        }
    }
    

    最后的执行结果


    image.png

    看图得出先后顺序是before、around、after、after return。但是xml配置的执行顺序就真的是这样的么?

    当我把上面xml配置的before和around换一个位置之后输出到结果

    image.png

    结果发生了变化,成为了around、before、after、after return

    注解

    <bean class="com.demo.Aop.AnimalImpl" id="animal" />
    <bean class="com.demo.Aop.AnimalAop" id="animalAop" />
    <!-- 上面两个bean 只是为了便于说明代码,也可以使用component-scan 配合相关注解完成-->
    
    <aop:aspectj-autoproxy />
    <!-- AOP注解核心配置,会生成相关的代理类-->
    
    // 接口类
    public interface Animal {
        void sleep(String name);
    }
    
    // 实现类
    public class AnimalImpl implements Animal {
    
        public AnimalImpl() {
            System.out.println("init");
        }
    
        public void sleep(String name) {
            System.out.println(name + " sleep");
        }
    }
    
    // 切面类
    public class AnimalAop {
    
        @Pointcut("execution(* com.demo.Aop.*.*(..))")
        public void pointCut(){}
        // 定义一个切点,会选择com.demo.Aop下面所有的类
    
        @Around("pointCut() && args(name)")
        public Object around(ProceedingJoinPoint pj, String name){
            // 定义为around注解,添加了切点,并且同时加上了参数
            Object obj = null;
            System.out.println(name + " around before");
            try {
                obj = pj.proceed();
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
            System.out.println(name + " around after");
            return obj;
        }
    
        @Before("pointCut() && args(name)")
        public void before(String name){
            System.out.println(name + " animal before");
        }
    
        @After("execution(* com.demo.Aop.*.*(..))")
        public void after(){
            // 这个直接使用了execution,而没有使用已经定义好的切点
            System.out.println("animal after");
        }
        
    }
    
    

    执行结果


    image.png

    在原本的实现类实现之后,执行的先后顺序为around、before、after、after return
    不过这里是没有XML注解的那种先后执行顺序,所有的执行顺序都是由spring自身决定的

    在当前的demo中可能注意到了,所使用的AnimalImpl是继承自Animal接口的,如果改成没有接口的情况呢?

    image.png image.png

    很明显 在使用接口的时候,spring会使用java的动态代理实现,否则会使用cglib实现代理功能

    demo基本上就完成了,后面的学习文章会具体分析XML配置和注解配置的实现细节以及同异

    相关文章

      网友评论

        本文标题:Spring AOP学习

        本文链接:https://www.haomeiwen.com/subject/ynnbzxtx.html