31--基于@AspectJ的AOP

作者: 闲来也无事 | 来源:发表于2018-11-09 09:50 被阅读21次

    上一节介绍了基于Schema的AOP,本篇介绍基于@AspectJ的AOP。

    1.@AspectJ切面
    • 目标对象
    package com.lyc.cn.v2.day07;
    
    public interface Animal {
        void sayHello();
    }
    
    package com.lyc.cn.v2.day07;
    
    public class Dog implements Animal {
        public void sayHello() {
            System.out.println("--被增强的方法");
        }
    }
    
    • 引介
    package com.lyc.cn.v2.day07;
    
    public interface IIntroduce {
        void sayIntroduce();
    }
    
    package com.lyc.cn.v2.day07;
    
    public class IntroduceImpl implements IIntroduce {
        @Override
        public void sayIntroduce() {
            System.out.println("--引入");
        }
    }
    
    • 切面
    package com.lyc.cn.v2.day07;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.*;
    
    /**
     * 切面类
     * @author: LiYanChao
     * @create: 2018-10-31 15:46
     */
    @Aspect
    public class DogAspect {
    
        /**
         * 例如:execution (* com.sample.service.impl..*.*(..)
         * 1、execution(): 表达式主体。
         * 2、第一个*号:表示返回类型,*号表示所有的类型。
         * 3、包名:表示需要拦截的包名,后面的两个点表示当前包和当前包的所有子包,
         * 即com.sample.service.impl包、子孙包下所有类的方法。
         * 4、第二个*号:表示类名,*号表示所有的类。
         * 5、*(..):最后这个星号表示方法名,*号表示所有的方法,后面括弧里面表示方法的参数,两个点表示任何参数。
         **/
        @Pointcut("execution(* com.lyc.cn.v2.day07.*.*(..))")
        public void test() {
    
        }
    
        @Before("test()")
        public void beforeTest() {
            System.out.println("==前置增强");
        }
    
        @After("test()")
        public void afterTest() {
            System.out.println("==后置最终增强");
        }
    
        @AfterThrowing("test()")
        public void afterThrowingTest() {
            System.out.println("==后置异常增强");
        }
    
        @AfterReturning("test()")
        public void afterReturningTest() {
            System.out.println("==后置返回增强");
        }
    
        @Around("test()")
        public Object aroundTest(ProceedingJoinPoint p) {
            System.out.println("==环绕增强开始");
            Object o = null;
            try {
                o = p.proceed();
            } catch (Throwable e) {
                e.printStackTrace();
            }
            System.out.println("==环绕增强结束");
            return o;
        }
    
        @DeclareParents(value = "com.lyc.cn.v2.day07.Dog", defaultImpl = IntroduceImpl.class)
        private IIntroduce iIntroduce;
    
    
    }
    
    • 配置文件
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <!--
            1、proxy-target-class
                如果被代理的目标对象至少实现了一个接口,则会使用JDK动态代理,所有实现该目标类实现的接口都将被代理
                如果该目标对象没有实现任何接口,则创建CGLIB动态代理。
                但是可以通过proxy-target-class属性强制指定使用CGLIB代理,
            2、expose-proxy
                解决目标对象内部的自我调用无法实施切面增强的问题
        -->
        <aop:aspectj-autoproxy proxy-target-class="true">
            <!-- 指定@Aspect类,支持正则表达式,符合该表达式的切面类才会被应用-->
            <aop:include name="dogAspect"></aop:include>
        </aop:aspectj-autoproxy>
    
        <!--bean-->
        <bean id="dog" class="com.lyc.cn.v2.day07.Dog"/>
    
        <!--AspectJ-->
        <bean name="dogAspect" class="com.lyc.cn.v2.day07.DogAspect"/>
    
    </beans>
    
    • 测试及结果
    package com.lyc.cn.v2.day07;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MyTest {
    
        @Test
        public void test1() {
            // 基于@AspectJ注解方式
            ApplicationContext ctx = new ClassPathXmlApplicationContext("v2/day07.xml");
            Dog dog = ctx.getBean("dog", Dog.class);
            dog.sayHello();
        }
    
    
        @Test
        public void test2() {
            // 引入
            ApplicationContext ctx = new ClassPathXmlApplicationContext("v2/day07.xml");
            // 注意:getBean获取的是dog
            IIntroduce introduce = ctx.getBean("dog", IIntroduce.class);
            introduce.sayIntroduce();
        }
    
    }
    
    // 测试一
    ==环绕增强开始
    ==前置增强
    --被增强的方法
    ==环绕增强结束
    ==后置最终增强
    ==后置返回增强
    
    // 测试二
    --引入
    
    2.总结

    前篇和本篇主要还是回顾了SpringAop的使用方式,也为了接下来的源码分析做好测试类准备,在接下来的分析中主要讲解以@AspectJ方式的实现方式。

    相关文章

      网友评论

        本文标题:31--基于@AspectJ的AOP

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