JavaEE

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

2022-10-13  本文已影响0人  平安喜乐698
目录

  概念
  示例(一般切面)
  示例(切点切面)
  示例(自动代理)
  示例(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();
    }
}
运行结果
上一篇下一篇

猜你喜欢

热点阅读