Spring 学习笔记

Spring AOP学习

2018-02-05  本文已影响9人  jwfy

AOP 概念了解

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

在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配置和注解配置的实现细节以及同异

上一篇下一篇

猜你喜欢

热点阅读