SpringAOP的使用

1. AOP 相关术语

  1. Joinpoint(连接点):
    所谓连接点是指那些被拦截到的点。在 spring 中,这些点指的是方法,因为 spring 只支持方法类型的
    连接点。
  2. Pointcut(切入点):
    所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义。
  3. Advice(通知/增强):
    所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知。
    通知的类型:前置通知,后置通知,异常通知,最终通知,环绕通知。
  4. Introduction(引介):
    引介是一种特殊的通知在不修改类代码的前提下, Introduction 可以在运行期为类动态地添加一些方
    法或 Field。
  5. Target(目标对象):
    代理的目标对象。
  6. Weaving(织入):
    是指把增强应用到目标对象来创建新的代理对象的过程。
    spring 采用动态代理织入,而 AspectJ 采用编译期织入和类装载期织入。
  7. Proxy(代理):
    一个类被 AOP 织入增强后,就产生一个结果代理类。
  8. Aspect(切面):
    是切入点和通知(引介)的结合。

3. 基于配置文件配置SpringAOP

先导入springc-ontext的坐标,和aspectjweaver的坐标

<dependency>
   <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.5.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.8.7</version>
</dependency>
  1. 提供一个类(UserServiceImpl),该类中的方法是需要被增强的。
public class UserServiceImpl implements IUserService {
    /**
     * 该方法需要被增强
     */
    public void showString() {
        System.out.println("UserServiceImpl中的showString方法!");
//        int i = 1/0;
    }
}
  1. 提供一个通知类(defor),该类定义了5中通知的方法
/**
	该类中定义的方法用来增强UserServiceImpl中的方法
*/
public class defor {
    public void beforeAdvice(){
        System.out.println("前置通知");
    }
    public void afterAdvice(){
        System.out.println("后置通知");
    }
    public void exceptionAdvice(){
        System.out.println("异常通知");
    }
    public void finallyAdvice(){
        System.out.println("最终通知");
    }
    public Object aroundAdvice(ProceedingJoinPoint p){
        System.out.println("环绕通知");
        try {
            System.out.println("前置通知");
            Object[] args = p.getArgs();
            Object proceed = p.proceed(args);
            System.out.println("后置通知");
            return proceed;
        } catch (Throwable t) {
            System.out.println("异常通知");
            t.printStackTrace();
            throw new RuntimeException(t);
        }finally {
            System.out.println("最终通知");
        }
    }
}
  1. 配置文件中引入约束
<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"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       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.xsd">
  1. 配置文件中先把这两个类配到容器中
<bean id="IUserService" class="com.itzpx.service.impl.UserServiceImpl"></bean>
<bean id="defor" class="com.itzpx.utils.defor"></bean>
  1. 配置通知
<aop:config>
 <aop:aspect id="deforAdvice" ref="defor">
     <aop:pointcut id="pointcutId" expression="execution(* com.itzpx.service.impl.*.*(..))"></aop:pointcut>
<!--<aop:before method="beforeAdvice" pointcut-ref="pointcutId"></aop:before>-->
<!--<aop:after-returning method="afterAdvice" pointcut-ref="pointcutId"></aop:after-returning>-->
<!--<aop:after-throwing method="exceptionAdvice" pointcut-ref="pointcutId"></aop:after-throwing>-->
<!--<aop:after method="finallyAdvice" pointcut-ref="pointcutId"></aop:after>-->
     <aop:around method="aroundAdvice" pointcut-ref="pointcutId"></aop:around>
 </aop:aspect>
</aop:config>
  1. 测试
public static void main(String[] args) {
	   ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
	   IUserService service = ac.getBean("IUserService", IUserService.class);
	   service.showString();
}

解释:
<aop:config>:aop的配置信息放里面
里面提供了三个标签
7. <aop:aspect id=“deforAdvice” ref=“defor”>:配置切面
id是唯一标识,随便写,ref是通知类bean的唯一标识
8. <aop:pointcut id=“pointcutId” expression=“execution(* com.itzpx.service.impl..(…))”></aop:pointcut>:配置切入点
id是唯一标识,expression指定哪个方法需要被增强
标准写法是:
public void com.包名.包名.等等.类名.方法名(参数),
通配写法是
访问修饰符省略

这种写法匹配所有的类,显然不符合我们的要求
* *..*.*(..)
我们需要加以限定
* * com.itzpx.service.impl.*.*(..)
  1. 在 <aop:aspect id=“deforAdvice” ref=“defor”>下面提供了
<aop:aspect id="deforAdvice" ref="defor">
   <aop:pointcut id="pointcutId" expression="execution(* com.itzpx.service.impl.*.*(..))"></aop:pointcut>
    <aop:before method="beforeAdvice" pointcut-ref="pointcutId"></aop:before>
    <aop:after-returning method="afterAdvice" pointcut-ref="pointcutId"></aop:after-returning>
    <aop:after-throwing method="exceptionAdvice" pointcut-ref="pointcutId"></aop:after-throwing>
    <aop:after method="finallyAdvice" pointcut-ref="pointcutId"></aop:after>
    <aop:around method="aroundAdvice" pointcut-ref="pointcutId"></aop:around>
</aop:aspect>

五个标签,分别代表了
pointcut 提取expression
before配置前置通知
after-returning后置通知
after-throwing异常通知
after最终通知
around环绕通知

4.关于环绕通知的问题

环绕通知其实是提供了一种编码编写通知的方式
在环绕通知中,包含了其他四种通知
ProceedingJoinPoint ,是spring提供的类
与我们动态代理中的involved方法类似用法

5.注解配置AOP

<!--1.将IUserService与defor放入容器-->
<bean id="IUserService" class="com.itzpx.service.impl.UserServiceImpl"></bean>
<bean id="defor" class="com.itzpx.utils.defor"></bean>

<aop:config>
<!--2.标识出通知类-->
    <aop:aspect id="deforAdvice" ref="defor">
    <!--3.切入点的配置,也就是指定需要被增强的方法-->
        <aop:pointcut id="pointcutId" expression="execution(* com.itzpx.service.impl.*.*(..))"></aop:pointcut>
        <!--4.指定通知方法,并与需要被增强的方法联系起来-->
        <aop:before method="beforeAdvice" pointcut-ref="pointcutId"></aop:before>
        <aop:after-returning method="afterAdvice" pointcut-ref="pointcutId"></aop:after-returning>
        <aop:after-throwing method="exceptionAdvice" pointcut-ref="pointcutId"></aop:after-throwing>
        <aop:after method="finallyAdvice" pointcut-ref="pointcutId"></aop:after>
        <aop:around method="aroundAdvice" pointcut-ref="pointcutId"></aop:around>
    </aop:aspect>
</aop:config>
  1. 将IUserService与defor放入容器
<context:component-scan base-package="com.itzpx"/>
@Component
public class defor {
@Component
public class UserServiceImpl implements IUserService {
  1. 标识出通知类
@Component
@Aspect//代表通知类
public class defor {
  1. 切入点的配置,也就是指定需要被增强的方法
@Pointcut("execution(* com.itzpx.service.impl.*.*(..))")
private void pt1(){}
  1. 指定通知方法,并与需要被增强的方法联系起来
@Before("pt1()")
    public void beforeAdvice(){
        System.out.println("前置通知");
    }
    @AfterReturning("pt1()")
    public void afterAdvice(){
        System.out.println("后置通知");
    }
    @AfterThrowing("pt1()")
    public void exceptionAdvice(){
        System.out.println("异常通知");
    }
    @After("pt1()")
    public void finallyAdvice(){
        System.out.println("最终通知");
    }
    @Around("pt1()")
    public Object aroundAdvice(ProceedingJoinPoint p){
        System.out.println("环绕通知");
        try {
            System.out.println("前置通知");
            Object[] args = p.getArgs();
            Object proceed = p.proceed(args);
            System.out.println("后置通知");
            return proceed;
        } catch (Throwable t) {
            System.out.println("异常通知");
            t.printStackTrace();
            throw new RuntimeException(t);
        }finally {
            System.out.println("最终通知");
        }
    }
  1. 开启springAOP注解配置
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值