SpringAop介绍与实战

AOP: Aspect Oriented Programming ,面向且边切面编程,即在不破坏原有对象、不需要更改原代码的基础上,实现方法功能的增强。说切面,是因为它不需要像传统OOP那样,纵向继承,只需要横向扩展即可。

AOP的实现可通过AspectJ以及Spring AOP两种方案,Spring并不是直接使用AspectJ,但其使用了AspectJ的注解方案,随后在运行时通过动态代理生成代理类。AspectJ是在编译时注入的。

在AOP中比较重要的几个概念:

1、Target:目标类,需要被增强的类。

2、JointPoint:连接点,目标类上每一个方法都可以是连接点。这个很好理解,AOP是基于动态代理的。

3、PointCut:切入点,被增强的方法,切入点就是一个连接点的子集

4、Advice:增强/通知,增强的代码,也就是上面将增强的代码凑成的一个类。类中的每个方法都代表一个增强的功能代码,这个类中的方法就被称为通知。pring AOP提供了5种Advice类型:前置、后置、返回、异常、环绕。

5、weaving:织入,将切入点和通知结合,从没被增强到已经增强的过程

6、Aspect:切面,切入点和通知结合,切入点 和 通知点 多点形成面。

例子1:

1、实现AOP Bean,


@Slf4j
@Component
@Aspect
public class ProxyAop {


    @Pointcut("execution(public * com.hnshop.hbnnshop.prac..*.*(..))")
    private void controllerAspect(){}

    @Around("controllerAspect()")
    public Object handleControllerMethod(ProceedingJoinPoint pjp) {
        log.info("start to execute aop method ");
        try
        {
            return pjp.proceed(pjp.getArgs());
        }catch (Throwable e){
            log.error(e.getMessage());
            return  "server error";
        }
    }


    @Before("controllerAspect()")
    public void before(){
        log.info("before aop method exec");
    }

    @After("controllerAspect()")
    public void after(){
        log.info("after aop method");
    }
}

上面几个注解的意思:

2.1 @Aspect

作用是把当前类标识为一个切面供容器读取。此时所有涉及到的Bean都会创建代理对象。但该类本身不会。

2.2 @Before
标识一个前置增强方法,相当于BeforeAdvice。

2.3 @AfterReturning

后置增强,相当于AfterReturningAdvice,方法正常退出时执行

2.4 @AfterThrowing

异常抛出增强,相当于ThrowsAdvice

2.5 @After

final增强,不管是抛出异常或者正常退出都会执行

2.6 @Around

环绕增强,相当于MethodInterceptor

我们要测试一个目标类:


@Component
public class IeratorPra {

    public List<Integer> getList(){
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        return list;
    }


    public void testIteratorRemove(){
        List<Integer> list = this.getList();
        ListIterator<Integer> integerListIterator = list.listIterator();
        while (integerListIterator.hasNext()){
            if(integerListIterator.next() == 4){
                integerListIterator.remove();
            }
        }
        System.out.println(list);
    }
}

调用:

public class ListPra extends HbnnshopApplicationTests {

    @Autowired
    IeratorPra ieratorPra;

    @Test
    public void test(){
        System.out.println(ieratorPra.getClass().getName());
        ieratorPra.testIteratorRemove();
    }

测试一下输出结果:

看到输出结果可以看到,生成了一个代理对象,且因为目标类没有实现接口,所以使用了CGLIB代理。

例子二(通过注解的方式)

定义注解和AOP:

//目标方法
@Target(ElementType.METHOD)
//保留到JVM
@Retention(RetentionPolicy.RUNTIME)
 //JAVADOC
@Documented
//自动继承
@Inherited
public @interface TestAno {

}


@Slf4j
@Component
@Aspect
public class TestAop {

    @Pointcut("@annotation(com.hnshop.hbnnshop.core.annotation.TestAno)")
    private void annoAspect(){}

    @Around("annoAspect()")
    public Object handleControllerMethod(ProceedingJoinPoint pjp) {
        log.info("start to execute aop method ");
        try
        {
            return pjp.proceed(pjp.getArgs());
        }catch (Throwable e){
            log.error(e.getMessage());
            return  "server error";
        }
    }


    @Before("annoAspect()")
    public void before(){
        log.info("before aop method exec");
    }

    @After("annoAspect()")
    public void after(){
        log.info("after aop method");
    }
}

目标类的方法使用注解:


    @TestAno
    public void testIteratorRemove(){
        List<Integer> list = this.getList();
        ListIterator<Integer> integerListIterator = list.listIterator();
        while (integerListIterator.hasNext()){
            if(integerListIterator.next() == 4){
                integerListIterator.remove();
            }
        }
        System.out.println(list);
    }

输出结果和上面类似:

参考资料:

Spring AOP就是这么简单啦

彻底征服 Spring AOP 之 实战篇

--------EOF---------
微信分享/微信扫码阅读