美文网首页JavaEE
JavaWeb了解之Spring框架(Spring AOP篇)

JavaWeb了解之Spring框架(Spring AOP篇)

作者: 平安喜乐698 | 来源:发表于2022-10-13 22:36 被阅读0次
    目录
    
      概念
      示例(一般切面)
      示例(切点切面)
      示例(自动代理)
      示例(AspectJ xml方式)
      示例(AspectJ 注解方式)
    

    AOP:面向切面编程(在运行时动态地将代码切入到指定类的指定方法的指定位置上)。
    可以在不修改源码的情况下给类添加新功能(通常是一些可复用的功能,如:日志功能、事务功能、权限检查、参数检查、统计信息,减少代码的重复性)。

    概念

    动态代理机制(2种)
      Spring在运行期会为目标对象生成一个动态代理对象(对目标对象进行增强)。
      1. JDK方式(默认)
        若目标对象实现了若干接口,Spring则使用JDK的java.lang.reflect.Proxy类进行代理。
      2. CGLIB方式    
        若目标对象没有实现任何接口,Spring则使用CGLIB库生成目标对象的子类进行代理。
      注意:声明为final类型的方法无法被覆盖,所以无法完成代理。
    
    切入点
      SpringAOP属于简化版AOP组件,并没有像其他AOP框架(如 AspectJ)提供完整的AOP功能。
      SpringAOP只支持方法调用(仅支持public类型且非static类型的方法)这一种切入点类型(最有用的切入点类型,可实现绝大多数AOP功能)。如果需要对private或protected类型的方法进行增强,或者需要使用其他类型的切入点(如:成员变量切入点),则需要组合其他AOP实现(如:ApectJ)来达成。
      将切入到指定类指定方法的代码片段称为切面,而切入到哪些类、哪些方法则叫切入点。
    
    通知类型
      org.aopalliance.aop.Interface.Advice接口。
      按照通知织入到目标对象方法的连接点位置,提供了6个Advice子接口:
        1. 前置通知 
          org.springframework.aop.MethodBeforeAdvice
          在目标方法执行前,执行通知(即进行增强)。
        2. 后置通知 
          org.springframework.aop.AfterReturningAdvice
          在目标方法执行后,无论是否异常,执行通知。
        3. 后置返回通知   
          org.springframework.aop.AfterReturningAdvice
          在目标方法执行后,且有返回值时,执行通知。
        4. 环绕通知 
          org.aopalliance.intercept.MethodInterceptor
          在目标方法执行前后,执行通知。
        5. 异常后通知    
          org.springframework.aop.ThrowsAdvice
          在目标方法抛出异常时,执行通知。
        6. 引入通知
          org.springframework.aop.IntroductionInterceptor   
          在目标类中添加新的方法和属性。
    
    切面类型
      对通知和切入点进行管理。
      分为3类:
        1. 一般切面(不带切点的切面)默认
          org.springframework.aop.Advisor接口。仅有一个Advice通知类型的属性,没有定义切入点。
          会对目标对象中的所有方法进行拦截并织入增强代码(由于太过宽泛,一般不使用)。
        2. 切点切面
          org.springframework.aop.PointcutAdvisor接口(Advisor的子接口),多了一个PointCut类型的属性。
          可以通过包名、类名、方法名等信息,更加灵活地定义切面中的切入点(即描述需要拦截的方法)。
          常用的实现类:
            1. NameMatchMethodPointcutAdvisor类
              指定Advice通知所要应用到的目标方法名。例如: hello* 代表所有以hello开头的方法。
            2. RegExpMethodPointcutAdvisor类
              有一个pattern属性(使用正则表达式来定义切点)。
        3. 引介切面
          org.springframework.aop.IntroductionAdvisor接口(Advisor的子接口)。
          对引介增强的特殊切面(应用于类层面上,适用ClassFilter进行定义)。
    
    ProxyFactoryBean
      Spring能够基于org.springframework.aop.framework.ProxyFactoryBean类,根据目标对象(是否实现了接口)自动选择使用 JDK动态代理或 CGLIB动态代理机制,为目标对象(TargetBean)生成对应的代理对象(ProxyBean)。
      常用的属性:
        1. target   
          需要被代理的目标对象(即需要增强的对象)。
        2. proxyInterfaces  
          代理对象需要实现的接口(多个接口时使用list元素进行赋值)。
        3. proxyTargetClass     
          针对类的代理。为false(默认)表示使用JDK动态代理;为true表示使用CGlib动态代理。
        4. interceptorNames     
          拦截器的名字(拦截器、Advice、切面 对应的Bean)。
        5. singleton    
          代理对象是否为单例模式(默认为true)。
        6. optimize     
          是否对代理对象进行优化(只适用于CGLIB)。
    
    自动代理
      在实际开发中,一个项目中往往包含非常多的Bean,如果每个Bean都通过在xml文件中使用ProxyFactoryBean创建代理对象,那么开发和维护成本会十分巨大,为此Spring提供了自动代理。
      Spring提供的自动代理方案,都是基于后处理Bean实现的(即在Bean创建的过程中完成增强),并将目标对象替换为自动生成的代理对象。在程序中直接拿到的Bean就已经是Spring自动生成的代理对象了。
      自动代理方案(3种):
        1. BeanNameAutoProxyCreator
          根据Bean名称 创建代理对象。
        2. DefaultAdvisorAutoProxyCreator
          根据Advisor信息 创建代理对象。
        3. AnnotationAwareAspectJAutoProxyCreator
          根据Bean中的AspectJ注解 创建自动代理对象。
    
    集成AspectJ
      AspectJ是一款独立的基于Java语言的全功能AOP框架,并不是Spring组成部分。
      AspectJ支持通过Spring配置AspectJ切面,因此它是SpringAOP的完美补充,工作中通常将2者结合使用来简化AOP开发。
      需要导入spring-aop-xxx.jar、spring-aspects-xxx.jar(Spring提供),aspectjweaver-xxxx.jar(AspectJ提供)。
      1. 使用步骤(XML方式):
        切面信息(切面、切点、通知)定义在aop:config元素中;aop:config元素可以有多个;
        1. 引入aop命名空间。
        2. 使用aop:aspect元素定义切面。
          <aop:config>
            <aop:aspect id="helloAspect" ref="aspectBean">
              ...
            </aop:aspect>
          </aop:config>    
        3. 使用aop:pointcut元素定义切点(对哪个方法进行增强)。
          <aop:config>
            <!-- 对包下的所有类中的所有方法进行增强 -->
            <aop:pointcut id="helloPointCut" expression="execution(* com.sst.cx.*.*(..))"/>
          </aop:config>
          说明:
          1. 当aop:pointcut元素定义在aop:config元素下时,表示该切点为全局切入点,可被多个切面共享;当aop:pointcut元素定义在aop:aspect元素下时,表示该切点只对当前切面有效。
          2. aop:pointcut元素的execution属性用于指定切入点所关联的切入点表达式。
            语法格式:execution([权限修饰符][返回值类型][类的完全限定名][方法名][参数列表])
            1. 返回值类型、方法名、参数列表 为必填,其他参数可选。
            2. 返回值类型:*表示任何返回值。当返回值为对象时需指定类的完整路径。
            3. 方法:*表示所有方法,hello*表示以hello开头的所有方法。
            4. 参数列表:(..)表示所有参数;(*)表示只有一个参数,参数类型任意;(*,String)表示有2个参数。
        4. 使用aop:aspect元素定义通知(5种类型)。
          <aop:aspect id="helloAspect" ref="实现下面5个方法的bean">
            <aop:before method="before" pointcut-ref="前面定义的切点id"></aop:before>
            <aop:after-returning method="afterReturning" pointcut-ref="前面定义的切点id" returning="returningValue"></aop:after-returning>
            <aop:after-throwing method="afterThrow" pointcut-ref="前面定义的切点id" throwing="exception"></aop:after-throwing>
            <aop:after method="after" pointcut-ref="前面定义的切点id"></aop:after>
            <aop:around method="around" pointcut-ref="前面定义的切点id"></aop:around>
          </aop:aspect> 
      2. 使用步骤(注解方式):
        1. 开启 @AspectJ注解。
          方式1. 在beans元素的开始处添加
            <!-- 开启注解扫描 -->
            <context:component-scan base-package="com.sst.cx"></context:component-scan>
            <!-- 开启@AspectJ注解 -->
            <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
          方式2. 在AppConfig.java类(使用@Configuration注解标注的类)中,添加@EnableAspectJAutoProxy注解和@ComponentScan(basePackages="com.sst.cx")注解。该类用于获取容器:ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);。
        2. 在UserDaoAdvice上添加
          @Component注解:相当于在xml中注册Bean。
          @Aspect注解:定义成切面。
        3. 在UserDaoAdvice的各个方法上添加通知注解
          方式1. 使用切入点表达式
            @Before(value="execution(* com.sst.cx.dao.UserDao.add(..))")
          方式2. 使用切入点引用
            @Before("UserDaoAdvice.pointCut1()")
            //
            定义切点
              可以使用切点表达式;也可以引用其他切点:@Pointcut(value="pointCut2"),引用其他切入点时可以使用 !、&&、|| :@Pointcut(value="!pointCut2()")。
              @Pointcut(value="execution(* com.sst.cx.dao.UserDao.add(..))")
              // 方法要求:private类型,返回值为void,没有参数
              private void pointCut1(){}
        //
        AspecjJ提供了如下注解:
          1. @Aspect    
            用于定义一个切面。
          2. @Pointcut  
            用于定义一个切入点。
          3. @Before    
            用于定义前置通知,相当于 BeforeAdvice。
          4. @AfterReturning    
            用于定义后置返回通知,相当于 AfterReturningAdvice。
          5. @Around    
            用于定义环绕通知,相当于 MethodInterceptor。
          6. @AfterThrowing 
            用于定义异常抛出通知,相当于 ThrowAdvice。
          7. @After 
            用于定义后置通知,相当于 AfterAdvice。
          8. @DeclareParents    
            用于定义引介通知,相当于 IntroductionInterceptor。
      
    

    示例(一般切面)

    如果没有对切面进行具体定义,SpringAOP会通过Advisor定义一个一般切面(不带切点的切面)。

    1. 导入依赖包
    
      4个核心jar:beans、context、core、expression
      AOP特性jar:aop
      三方jar:commons-logging.jar
    
    2.
    
    ===》UserDao.java(DAO接口)
    package com.sst.cx.dao;
    public interface UserDao {
        public void add();
        public void delete();
        public void update();
        public void querry();
    }
    ===》UserDaoImpl.java(DAO实现)
    package com.sst.cx.dao.impl;
    import com.sst.cx.dao.UserDao;
    public class UserDaoImpl implements UserDao {
        @Override
        public void add() {
            System.out.println("执行add方法。。。");
        }
        @Override
        public void delete() {
            System.out.println("执行delete方法。。。");
        }
        @Override
        public void update() {
            System.out.println("执行update方法。。。");
            
        }
        @Override
        public void querry() {
            System.out.println("执行querry方法。。。");
        }
    }
    
    ===》UserDaoBeforeAdvice.java(Advice通知,拦截器)
    package com.sst.cx.advice;
    import java.lang.reflect.Method;
    import org.springframework.aop.MethodBeforeAdvice;
    public class UserDaoBeforeAdvice implements MethodBeforeAdvice {
        @Override
        public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
            System.out.println("前置增强操作。。。");
        }
    }
    
    3. 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:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
            <!-- 目标对象(需要增强的对象) -->
            <bean id="userDaoImpl" class="com.sst.cx.dao.impl.UserDaoImpl"></bean>
            <!-- 定义增强 -->
            <bean id="beforeAdvice" class="com.sst.cx.advice.UserDaoBeforeAdvice"></bean>
            <!-- 通过配置生成代理userDaoImpl的 代理对象 -->
            <bean id="userDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
                <!-- 设置 被代理的目标对象(需增强的对象) -->
                <property name="target" ref="userDaoImpl"/>
                <!-- 设置 代理对象需实现的接口(全路径) -->
                <property name="proxyInterfaces" value="com.sst.cx.dao.UserDao"/>
                <!-- 设置 拦截器(增强) -->
                <property name="interceptorNames" value="beforeAdvice"/>
        </bean>
    </beans>
    
    4. 测试
    
    ===》MainApp.java
    package com.sst.cx;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import com.sst.cx.dao.UserDao;
    public class MainApp {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
            // 获取代理对象
            UserDao userDao = (UserDao)context.getBean("userDaoProxy");
            userDao.add();
            userDao.delete();
            userDao.update();
            userDao.querry();
        }
    }
    
    运行结果

    示例(切点切面)

    1. 导入依赖包
      同上
    
    2. UserDao.java、userDaoImpl.java
      同上
    
    这次换一种通知类型:环绕通知
    ===》UserDaoAroundAdvice.java(Advice通知,拦截器)
    package com.sst.cx.advice;
    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;
    public class UserDaoAroundAdvice implements MethodInterceptor {
        @Override
        public Object invoke(MethodInvocation methodInvocation) throws Throwable {
            System.out.println("前置增强操作。。。");
            // 执行目标方法(被代理对象中的逻辑)
            Object result = methodInvocation.proceed();
            System.out.println("后置增强操作。。。");
            return result;
        }
    }
    
    3. 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:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
            <!-- 目标对象(需要增强的对象) -->
            <bean id="userDaoImpl" class="com.sst.cx.dao.impl.UserDaoImpl"></bean>
            <!-- 定义增强 -->
            <bean id="aroundAdvice" class="com.sst.cx.advice.UserDaoAroundAdvice"></bean>
            <!-- 定义切面 -->
            <bean id="myPointCutAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
                <!--拦截哪些方法。 value设为.*则表示所有方法-->
                <property name="patterns" value="com.sst.cx.dao.impl.UserDaoImpl.add.*,com.sst.cx.dao.impl.UserDaoImpl.delete.*"></property>
                <property name="advice" ref="aroundAdvice"></property>
            </bean>
            <!-- 通过配置生成代理userDaoImpl的 代理对象 -->
            <bean id="userDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
                <!-- 设置 被代理的目标对象(需增强的对象) -->
                <property name="target" ref="userDaoImpl"/>
                <!-- 设置 代理对象需实现的接口(全路径) -->
                <property name="proxyInterfaces" value="com.sst.cx.dao.UserDao"/>
                <!-- 设置 拦截器(增强) -->
                <property name="interceptorNames" value="myPointCutAdvisor"/>
            </bean>
    </beans>
    
    4. 测试
      同上
    
    运行结果

    示例(自动代理)

    将上面的 切点切面示例 改为自动代理。

    ===》方式1. BeanNameAutoProxyCreator
    修改xml文件内容如下:
      去除切面Bean、ProxyFactoryBean,添加自动代理Bean。
            <!-- 目标对象(需要增强的对象) -->
            <bean id="userDaoImpl" class="com.sst.cx.dao.impl.UserDaoImpl"></bean>
            <!-- 定义增强 -->
            <bean id="aroundAdvice" class="com.sst.cx.advice.UserDaoAroundAdvice"></bean>
            <!-- 自动代理,对所有后缀为Impl的Bean自动创建代理对象,对所有方法进行aroundAdvice增强 -->
            <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
                <property name="beanNames" value="*Impl"></property>
                <property name="interceptorNames" value="aroundAdvice"></property>
            </bean>
    
    
    ===》方式2. DefaultAdvisorAutoProxyCreator
    修改xml文件内容如下:
      去除ProxyFactoryBean,添加自动代理Bean。
            <!-- 目标对象(需要增强的对象) -->
            <bean id="userDaoImpl" class="com.sst.cx.dao.impl.UserDaoImpl"></bean>
            <!-- 定义增强 -->
            <bean id="aroundAdvice" class="com.sst.cx.advice.UserDaoAroundAdvice"></bean>
            <!-- 定义切面 -->
            <bean id="myPointCutAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
                <!--拦截哪些方法。 value设为.*则表示所有方法-->
                <property name="patterns" value="com.sst.cx.dao.impl.UserDaoImpl.add.*,com.sst.cx.dao.impl.UserDaoImpl.delete.*"></property>
                <property name="advice" ref="aroundAdvice"></property>
            </bean>
            <!-- 自动代理,根据切面信息自动创建代理对象,对指定方法进行增强 -->
            <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>
    
    测试文件中直接使用userDaoImpl获取代理对象:context.getBean("userDaoImpl")
    

    示例(AspectJ)

    1. 导入依赖包
    
      4个核心jar:beans、context、core、expression
      AOP特性jar:aop、aspects(Spring提供),aspectjweaver(aspectJ提供)
      三方jar:commons-logging.jar
    
    2. UserDao.java、userDaoImpl.java、UserDaoAdvice.java
    
    ===》UserDao.java(DAO接口)
    package com.sst.cx.dao;
    public interface UserDao {
        public void add();
        public void delete();
        public int update();
        public void querry();
        public void throwException();
    }
    
    ===》userDaoImpl.java(DAO实现)
    package com.sst.cx.dao.impl;
    import com.sst.cx.dao.UserDao;
    public class UserDaoImpl implements UserDao {
        @Override
        public void add() {
            System.out.println("执行add方法。。。");
        }
        @Override
        public void delete() {
            System.out.println("执行delete方法。。。");
        }
        @Override
        public int update() {
            System.out.println("执行update方法。。。");
            return 100;
        }
        @Override
        public void querry() {
            System.out.println("执行querry方法。。。");
        }
        @Override
        public void throwException() {
            System.out.println("执行throwException方法。。。");
            int x=1/0;
        }
    }
    
    ===》UserDaoAdvice.java(Advice通知,拦截器)
    package com.sst.cx.advice;
    import org.aspectj.lang.ProceedingJoinPoint;
    public class UserDaoAdvice {
        public void before() {
            System.out.println("前置增强操作。。。");
        }
        public void after() {
            System.out.println("后置增强操作。。。");
        }
        public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
            System.out.println("环绕前置增强操作。。。");
            proceedingJoinPoint.proceed();
            System.out.println("环绕后置增强操作。。。");
        }
        public void afterReturning(Object returnValue) {
            System.out.println("后置返回增强操作。。。"+returnValue);
        }
        public void afterThrow(Throwable exception) {
            System.out.println("异常增强操作。。。"+exception.getMessage());
        }   
    }
    
    3. 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-3.0.xsd 
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
        <!-- 定义Bean -->
        <bean id="userDaoImpl" class="com.sst.cx.dao.impl.UserDaoImpl"></bean>
        <!-- 定义通知(增强) -->
        <bean id="myAdvice" class="com.sst.cx.advice.UserDaoAdvice"></bean>
        <aop:config>
            <aop:pointcut id="beforePointCut" expression="execution(* com.sst.cx.dao.UserDao.add(..))"/>
            <aop:pointcut id="afterPointCut" expression="execution(* com.sst.cx.dao.UserDao.delete(..))"/>
            <aop:pointcut id="afterReturnPointCut" expression="execution(* com.sst.cx.dao.UserDao.update(..))"/>
            <aop:pointcut id="aroundPointCut" expression="execution(* com.sst.cx.dao.UserDao.querry(..))"/>
            <aop:pointcut id="throwPointCut" expression="execution(* com.sst.cx.dao.UserDao.throwException(..))"/>      
            <aop:aspect ref="myAdvice">
                <aop:before method="before" pointcut-ref="beforePointCut"></aop:before>
                <aop:after-returning method="afterReturn"
                    pointcut-ref="afterReturnPointCut" returning="returnValue"></aop:after-returning>
                <aop:after-throwing method="afterThrow"
                    pointcut-ref="throwPointCut" throwing="exception"></aop:after-throwing>
                <aop:after method="after" pointcut-ref="afterPointCut"></aop:after>
                <aop:around method="around" pointcut-ref="aroundPointCut"></aop:around>
            </aop:aspect>
        </aop:config>
    </beans>
    
    4. 测试
    
    ===》MainApp.java
    package com.sst.cx;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import com.sst.cx.dao.UserDao;
    public class MainApp {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
            UserDao userDao = context.getBean("userDaoImpl",UserDao.class);
            userDao.add();
            userDao.delete();
            userDao.update();
            userDao.querry();
            userDao.throwException();
        }
    }
    
    运行结果

    示例(AspectJ 注解方式)

    1. 导入依赖包
    
      4个核心jar:beans、context、core、expression
      AOP特性jar:aop、aspects(Spring提供),aspectjweaver(aspectJ提供)
      三方jar:commons-logging.jar
    
    2. UserDao.java、userDaoImpl.java、UserDaoAdvice.java
    
    ===》UserDao.java(DAO接口)
    package com.sst.cx.dao;
    public interface UserDao {
        public void add();
        public void delete();
        public int update();
        public void querry();
        public void throwException();
    }
    
    ===》userDaoImpl.java(DAO实现)
    package com.sst.cx.dao.impl;
    import org.springframework.stereotype.Component;
    import com.sst.cx.dao.UserDao;
    @Component("userDaoImpl")
    public class UserDaoImpl implements UserDao {
        @Override
        public void add() {
            System.out.println("执行add方法。。。");
        }
        @Override
        public void delete() {
            System.out.println("执行delete方法。。。");
        }
        @Override
        public int update() {
            System.out.println("执行update方法。。。");
            return 100;
        }
        @Override
        public void querry() {
            System.out.println("执行querry方法。。。");
        }
        @Override
        public void throwException() {
            System.out.println("执行throwException方法。。。");
            int x=1/0;
        }
    }
    
    ===》UserDaoAdvice.java(Advice通知,拦截器)
    package com.sst.cx.advice;
    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.springframework.stereotype.Component;
    @Component
    @Aspect
    public class UserDaoAdvice {
        @Before(value="execution(* com.sst.cx.dao.UserDao.add(..))")
        public void before() {
            System.out.println("前置增强操作。。。");
        }
        @After(value="execution(* com.sst.cx.dao.UserDao.delete(..))")
        public void after() {
            System.out.println("后置增强操作。。。");
        }
        @Around(value="execution(* com.sst.cx.dao.UserDao.querry(..))")
        public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
            System.out.println("环绕前置增强操作。。。");
            proceedingJoinPoint.proceed();
            System.out.println("环绕后置增强操作。。。");
        }
        @AfterReturning(value="execution(* com.sst.cx.dao.UserDao.update(..))",returning="returnValue")
        public void afterReturn(Object returnValue) {
            System.out.println("后置返回增强操作。。。返回值:"+returnValue);
        }
        @AfterThrowing(value="execution(* com.sst.cx.dao.UserDao.throwException(..))",throwing="exception")
        public void afterThrow(Throwable exception) {
            System.out.println("异常增强操作。。。异常信息:"+exception.getMessage());
        }   
    }
    
    4. 测试
    
    ===》MainApp.java
    package com.sst.cx;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import com.sst.cx.dao.UserDao;
    public class MainApp {
        public static void main(String[] args) {
            ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
            // 获取代理对象
            UserDao userDao = context.getBean("userDaoImpl",UserDao.class);
            userDao.add();
            userDao.delete();
            userDao.update();
            userDao.querry();
            userDao.throwException();
        }
    }
    
    运行结果

    相关文章

      网友评论

        本文标题:JavaWeb了解之Spring框架(Spring AOP篇)

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