• Spring-aspectJ


    1. 介绍

    通过aspectJ,使用aspectJ,就不用像之前一样,切面类需要继承一些切面父类了,可以随意自定义一个切面类,然后配置一下就可以了,可以通过配置的方式,也可以通过注解的方式

    2. xml配置方式

    实现类

    package com.test.spring.aspectJ;
    
    public class UserServiceImpl implements UserService{
    
        public void addUser() {
            System.out.println("添加用户");
        }
    
        public void deleteUser() {
            System.out.println("删除用户");
            
        }
    
        public void editUser() {
            System.out.println("修改用户");
            
        }
    
    }

    切面类

    public class MyAspect {
        
        public void monitorBefore() {
            System.out.println("执行前");
        }
    }

    xml配置

    <?xml version="1.0" encoding="UTF-8" ?>
    <beans   xmlns="http://www.springframework.org/schema/beans" 
             xmlns:context="http://www.springframework.org/schema/context"
             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/context
                                  http://www.springframework.org/schema/context/spring-context.xsd
                                  http://www.springframework.org/schema/aop
                                  http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
            
            <!-- 实现类 -->
            <bean id="userService" class="com.test.spring.aspectJ.UserServiceImpl"></bean>
            
         <!-- 切面类 -->
            <bean id="myAspect" class="com.test.spring.aspectJ.MyAspect"></bean>
            <aop:config>
           <!-- 切面配置 ref 对应面类-->
                <aop:aspect ref="myAspect" >
              <!-- 切入点,
                  expression对应执行方法的公式,这个公式很好理解,声明类型 返回值 包名.类名.方法名(参数类型) throws 抛出异常全限定名
                  id 切入点ID
              -->
                    <aop:pointcut expression="execution(* com.test.spring.aspectJ.UserServiceImpl.addUser())" id="addPointCut"/>
                    
              <!-- aop:before就是切入的类型,这里使用before意思就是在方法之前调用,method就是切入的方法,pointcut-ref就是切入点ID,
                  这里还可以自定义表达式,pointcut就是自己重新定义切入点表达式,这里使用pointcut或者pointcut-ref都可以 -->
              <aop:before method="monitorBefore" pointcut-ref="addPointCut"/> </aop:aspect> </aop:config> </beans>

    运行测试类

    package com.test.spring.aspectJ;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class TestAspectJ {
    
        @Test
        public void test() {
            ApplicationContext context = new ClassPathXmlApplicationContext("/com/test/spring/aspectJ/springConfig.xml");
        
            UserService userservice = context.getBean("userService",UserService.class);
        
            userservice.addUser();
            userservice.deleteUser();
            userservice.editUser();
            
        }
    }

    运行结果,可以看出,切面先执行切面方法在执行目标方法,并且可以看出,因为表达式中只对addUser的方法进行切入,所以只要在添加用户前才进行切入

    执行前
    添加用户
    删除用户
    修改用户

    这里我们注意的是所有的切入类型,如aop:before 或者aop:after,都可以没有入参,或者有一个或以上的参数,默认第一个参数为 Joinpoint, 这个对象里面包含了很多切入点的信息,包括切入的方法名,类名,等等的一些信息

    3.不同切入类型配置和切入类的写法

    • aop:before
    <aop:before method="monitorBefore" pointcut-ref="addPointCut"/>

    切面类方法

    public void monitorBefore(JoinPoint joinPoint) {
            System.out.println("执行前");
        }
    • aop:after-returning

    这里的return等于切入方法monitorAfter入参中,第二个参数名,用于告诉切入方法返回的值是什么

    <aop:after-returning method="afterReturning" pointcut-ref="addPointCut" returning="ret"/>

    切面类方法

    /**
         * 参数1 连接点的描述,包括目标函数的名称,字段
         * 参数2 类型Object,需要在配置指定名称 与这里的名称一致
         * @param joinPoint
         * @param ret
         */
        public void afterReturning(JoinPoint joinPoint, Object ret) {
            System.out.println("After Returning");
        }
    • aop:around
    <aop:around method="myAround" pointcut-ref="addPointCut"/>

    切面类方法,这里必须手动调用目标方法

    /**
         * 环绕
         * @param joinPoint
         * @return
         * @throws Throwable
         */
        public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable {
            System.out.println("前");
            Object obj = joinPoint.proceed();
            System.out.println("后");
            return obj;
        }
    • aop:after-throwing

    这里的throwing等于入参中的第二个方法,告诉切入点,异常的对象,当目标切入点方法执行并抛出异常,机会进入到这个切面类型当中

    <aop:after-throwing method="myThrow" pointcut-ref="addPointCut" throwing="e"/>

    切面类方法

    public void myThrow(JoinPoint joinPoint, Throwable e) {
            System.out.println("异常了");
        }
    • aop:after
    <aop:after method="monitorAfter" pointcut-ref="addPointCut"/>

    切面类方法

    /**
         * 
         * @param joinPoint 目标函数
         */
        public void monitorAfter(JoinPoint joinPoint) {
            
            System.out.println("执行后");
        }

    3.基于注解

    基于下面的xml配置,把它转化成注解的方式

    <?xml version="1.0" encoding="UTF-8" ?>
    <beans   xmlns="http://www.springframework.org/schema/beans" 
             xmlns:context="http://www.springframework.org/schema/context"
             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/context
                                  http://www.springframework.org/schema/context/spring-context.xsd
                                  http://www.springframework.org/schema/aop
                                  http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
            
            
            <bean id="userService" class="com.test.spring.aspectJ.UserServiceImpl"></bean>
            
            <bean id="myAspect" class="com.test.spring.aspectJ.MyAspect"></bean>
            
            <aop:config>
                <aop:aspect ref="myAspect" >
                    <aop:pointcut expression="execution(* com.test.spring.aspectJ.UserServiceImpl.addUser())" id="addPointCut"/>
                    <aop:before method="monitorBefore" pointcut-ref="addPointCut"/>
                    <aop:after-returning method="monitorAfter" pointcut-ref="addPointCut" returning="ret"/>
                    <aop:around method="myAround" pointcut-ref="addPointCut"/>
                    <aop:after-throwing method="myThrow" pointcut-ref="addPointCut" throwing="e"/>
                    <aop:after method="myThrow" pointcut-ref="addPointCut"/>
                </aop:aspect>
                
            </aop:config>
         
    </beans>

    这里分几个步骤

    • xml配置中,把所有的内容都去掉,只剩下组件扫描和aspectJ自定代理配置
    <?xml version="1.0" encoding="UTF-8" ?>
    <beans   xmlns="http://www.springframework.org/schema/beans" 
             xmlns:context="http://www.springframework.org/schema/context"
             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/context
                                  http://www.springframework.org/schema/context/spring-context.xsd
                                  http://www.springframework.org/schema/aop
                                  http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
            
            <context:component-scan base-package="com.test.spring.aspectJ.anno"></context:component-scan>
            
           <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
         
    </beans>
    • 在应用的bean中添加组件注解和切面类中添加注解

    实现类声明是bean

    package com.test.spring.aspectJ.anno;
    
    import org.springframework.stereotype.Component;
    
    @Component("UserServiceImpl")
    public class UserServiceImpl implements UserService{
    
        public void addUser() {
            System.out.println("添加用户");
        }
    
        public void deleteUser() {
            System.out.println("删除用户");
            
        }
    
        public void editUser() {
            System.out.println("修改用户");
            
        }
    
    }

    切面类

    package com.test.spring.aspectJ.anno;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.stereotype.Component;
    
    @Component
    @Aspect
    public class MyAspect {
        
    }
    • 切面类方法添加注解

    这里注意的是,我们可以在注解当中,假如只有一个属性,我们可以省略value=,假如是两个属性,必须有value值,表达式也可以写一个公共类,value只要指定对应的方法名即可

    声明公共表达式的方式,调用的时候,还需要@Before(value="pointCut()")即可,或者不用value, @Before("pointCut()")

    @Pointcut("execution(* com.test.spring.aspectJ.anno.UserServiceImpl.deleteUser())")
        private void pointCut() {
        }

    @Before

    @Before("execution(* com.test.spring.aspectJ.anno.UserServiceImpl.deleteUser())")
        public void monitorBefore(JoinPoint joinPoint) {
            System.out.println("执行前");
        }

    @AfterReturning

    @AfterReturning(value="pointCut()",returning="ret")
        public void afterReturning(JoinPoint joinPoint, Object myReturn) {
            System.out.println("After Returning");
        }

    @Around

    @Around(value="pointCut()")
        public Object myRound(ProceedingJoinPoint joinPoint) throws Throwable {
            System.out.println("前");
            Object obj = joinPoint.proceed();
            System.out.println("后");
            return obj;
        }

    @AfterThrowing

    @AfterThrowing(value="pointCut()",throwing = "e")
        public void afterThrowing(JoinPoint joinPoint, Throwable e) {
            System.out.println("异常了");
        }

    @After

    @After(value="pointCut()")
        public void monitorAfter(JoinPoint joinPoint) {
            
            System.out.println("执行后");
        }
  • 相关阅读:
    WPF 使用用户控件UserControl来切换界面(一)
    Halcon 定位与区域分割学习笔记
    Halcon 识别车牌学习笔记
    STM32CubeIDE printf 多个串口
    netcore 跨源资源共享CORS
    自定义Converter
    自定义ListBox
    ExtensionHelper扩展帮助类
    多选ComboBox
    log4net + appsettings.json
  • 原文地址:https://www.cnblogs.com/oscar1987121/p/10949240.html
Copyright © 2020-2023  润新知