• (三)Spring超全面快速入门-AspectJ开发


    1、@AspectJ提供不同的通知类型

    • @Before 前置通知,相当于MethodBeforeAdvice

    • @AfterReturning 后置通知,相当于AfterReturningAdvice

    • @Around 环绕通知,相当于MethodInterceptor

    • @AfterThrowing异常抛出通知,相当于ThrowAdvice

    • @After 最终final通知,不管是否异常,该通知都会执行(相当于finally代码块)

    • @DeclareParents 引介通知,相当于IntroductionInterceptor(不必掌握)

    2、需要依赖的Jar包

    Spring四大基本包: spring-core, spring-context, spring-expression, spring-beans
    测试包: junit切记一定要4.1版本或以上,不要使用3.X版本的,否则@Runwith注解用不了
    spring测试包: spring-test
    AOP联盟aopaliance和spring-aop两个包
    AspectJ两个包 :aspectjweaver和spring-aspects

    3、入门案例

    还是老三样:目标类、通知类、配置信息
    目标类:

    package demo1;
    
    public class UserDaoImpl implements UserDao {
        @Override
        public void insert() {
            System.out.println("新增用户...");
        }
    
        @Override
        public void update() {
            System.out.println("更新用户...");
        }
    
        @Override
        public void delete() {
            System.out.println("删除用户...");
        }
    
        @Override
        public void findin() {
            System.out.println("查找用户...");
        }
    }
    
    

    通知类:

    package demo1;
    
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    
    @Aspect
    public class MyAspectJAnno {
    
        @Before(value="execution(* demo1.UserDaoImpl.*(..))")
        public void before() {
            System.out.println("==========前置通知========");
        }
    
    }
    
    

    需要注意的是应该在类前面加@Aspect注解,这样才能使其变成切面类,在要执行通知的前面加@Before注解,后面的value里面是"execution(要增强的目标类信息的包,正则表达式)"
    看下配置文件:

    <?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">
        <!--开启AspectJ的注解,自动代理-->
        <aop:aspectj-autoproxy/>
    
        <!--设置目标类-->
        <bean id="userDao" class="demo1.UserDaoImpl"/>
        <!--定义切面-->
        <bean class="demo1.MyAspectJAnno"/>
    </beans>
    

    看下运行结果:
    在这里插入图片描述
    是不是超级简单?

    4、@Before前置通知

    @Before
    可以在方法中传入JoinPoint对象,用来获得切点信息:
    在这里插入图片描述
    看下打印结果:
    在这里插入图片描述

    5、@AfterReturning后置通知

    @AfterReturning
    也很简单,和前置差不多,比如在查找方法后增加后置增强:

        @AfterReturning(value = "execution(* demo1.UserDaoImpl.findin(..))")
        public void afterReturning(JoinPoint joinPoint) {
            System.out.println("后置通知=========="+joinPoint);
        }
    

    在这里插入图片描述
    当然后置通知还可以返回参数,比如我们把findin方法改成了返回值为String的方法,然后,只需这样配置:
    在这里插入图片描述
    切记returning后的名字和afterReturning方法中的参数名字必须一样才行,看下打印结果:
    在这里插入图片描述
    这里就是我返回的String

    6、@Round环绕通知

    • around方法的返回值是目标代理方法的返回值
    • 参数为ProceedingJoinPoint可以调用拦截目标方法执行
      环绕通知可以在某个方法前后进行增强,当然也可以不执行这个方法,看个例子:
        @Around(value = "execution(* demo1.UserDaoImpl.delete(..))")
        public Object round(ProceedingJoinPoint joinPoint) throws Throwable {
            System.out.println("环绕前增强===========");
            Object obj = joinPoint.proceed();
            System.out.println("环绕后增强===========");
            return obj;
        }
    

    看一下打印结果:
    在这里插入图片描述

    7、@AfterThrowing异常抛出通知

    • 通过throwing属性,可以设置发生异常对象参数
      必须目标方法抛出异常后才会执行:
      在这里插入图片描述
      经典错误:
        @AfterThrowing(value = "execution(* demo1.UserDaoImpl.update())",throwing = "e")
        public void AfterThrowing(Throwable e) {
            System.out.println("异常抛出通知"+e.getMessage());
        }
    

    然后就可以在遇到错误时打印错误信息了:
    在这里插入图片描述

    8、@After最终通知

        @After(value = "execution(* demo1.UserDaoImpl.findin())")
        public void Final() {
            System.out.println("最终通知=======================================");
        }
    

    这样就可以完成最终通知,不管会不会报错都会在这个方法后执行:
    在这里插入图片描述

    9、@Pointcut为切点命名

    • 在每个通知内定义切点,会造成工作量巨大,不易维护,对于重复的切点,可以使用@Pointcut进行定义
    • 切点方法: private void无参数方法,方法名为切点名
    • 当通知有多个切点时,可是使用“||”进行连接
      使用方法:
        @Pointcut(value = "execution(* demo1.UserDaoImpl.findin())")
        private void demo1() {}
    

    只定义一个空方法,然后这个切点就是只增强findin();方法的,然后我们在需要增强findin的通知方法名写成demo1()就可以了:

        @After(value = "demo1()")
        public void Final() {
            System.out.println("最终通知=======================================");
        }
    

    这样就是在findin方法执行后执行最终通知:
    在这里插入图片描述
    可以看跟以前配置一样,这样就很方便的再次进行了解耦。

    10、基于XML的方式开发AOP

    目标类还是UserDao,我们看看切面类怎么写:

    package demo2;
    
    public class MySpringAdvicor {
    
        public void before() {
            System.out.println("-*-*-*-*-*-*XML前置增强通知*-*-*-*-*-*-*-");
        }
    }
    
    

    巨简单,什么都不用配置,因为要去配置文件配置,看看XML:

    <?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">
    
        <!--设置目标类-->
        <bean id="userDao" class="demo2.UserDaoImpl"/>
    
        <!--设置切面类-->
        <bean id="myAdvisor" class="demo2.MySpringAdvicor"/>
    
        <!--配置切面类-->
        <aop:config>
            <!--设置切入点-->
            <aop:pointcut id="pointcut1" expression="execution(* demo2.UserDao.delete(..))"/>
            <!--设置增强方式-->
            <aop:aspect ref="myAdvisor">
                <aop:before method="before" pointcut-ref="pointcut1"/>
            </aop:aspect>
        </aop:config>
    </beans>
    

    需要设置切面类,标签是aop:config,内部一个是aop:aspect表示的是切面是哪个,aop:pointcut表示切入点是哪个类,看看运行结果:
    在这里插入图片描述

  • 相关阅读:
    JSP(一)
    设计模式之UML类图
    Servle原理
    Servlet 浅谈(三)
    Servlet 浅谈(二)
    Servlet 浅谈(一)
    闲聊
    设计模式之装饰器模式
    struts2源码调试环境的搭建
    Github学习
  • 原文地址:https://www.cnblogs.com/taobean/p/12364250.html
Copyright © 2020-2023  润新知