spring学习笔记(8)AOP增强(advice)配置与应用

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: <div class="markdown_views"><h1 id="增强类型">增强类型</h1><p>增强(advice)主要包括如下五种类型 <br>1. 前置增强(BeforeAdvice):在目标方法执行前实施增强 <br>2. 后置增强(AfterReturningAdvice):在目标方法执行后实施增强 <br>3. 环绕增强(MrthodInter

增强类型

增强(advice)主要包括如下五种类型
1. 前置增强(BeforeAdvice):在目标方法执行前实施增强
2. 后置增强(AfterReturningAdvice):在目标方法执行后实施增强
3. 环绕增强(MrthodInterceptor):在目标方法执行前后实施增强
4. 异常抛出增强(ThrowsAdvice):在目标方法抛出异常后实施增强
5. 引介增强(IntroductionIntercrptor):在目标类中添加一些新的方法和属性

前置增强和后置增强配置

下面通过实例代码来分析前置增强,假如现在要作日志记录,记录了什么人调用什么方法。前置增强的配置可归纳为如下步骤:

1. 配置代理接口:

package test.aop;

public interface ITarget {
    String speak(String name);
}

2. 定义被代理对象

package test.aop;
//被代理对象
public class Target implements ITarget{

    private static final String name = "zenghao";
    @Override
    public String speak(Integer age){
        System.out.println("hello I'm " + age + " years old");
        return "I'm return value";
    }
    public static String getName() {
        return name;
    }
}

3. 配置增强

package test.aop;

import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;

public class BeforeAdvice implements MethodBeforeAdvice {
   /**
    * @param method:目标类的方法
    * args: 目标类的方法入参
    * obj:目标类实例
    * 
    */
   @Override
   public void before(Method method, Object[] args, Object target)
           throws Throwable {
       if(target instanceof Target){
           System.out.println("前置日志记录: "  +  ((Target)target).getName() + "调用了" + method.getName() + "方法,传入参数为:" + args[0] );
       }
   }

}
/*------------------分割线---------------------*/
package test.aop;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;

public class AfterAdvice implements  AfterReturningAdvice {
   /**
    * @param 
    * returnValue 返回值
    * method:目标类的方法
    * args: 目标类的方法入参
    * obj:目标类实例
    * 
    */
   @Override
   public void afterReturning(Object returnValue, Method method,
           Object[] args, Object target) throws Throwable {
       if(target instanceof Target){
           System.out.println("后置日志记录: "  +  ((Target)target).getName() + "调用了" + method.getName() + "方法,返回值为:" + returnValue );
       }
   }

}

4. 配置代理对象ProxyFactoryBean

PeoxyFactoryBean是FactoryBean的实现类,我们知道FactoryBean负责初始化Bean,而ProxyFactoryBean则负责为其他Bean创建代理实例,通过在xml中配置后注入使用

<!--  配置被代理对象 -->
<bean id="mytarget" class="test.aop.Target" />
<!-- 配置前置增强  -->
<bean id="myBeforeAdvice" class="test.aop.BeforeAdvice" />
<!-- 配置后置增强 -->
<bean id="myAfterReturnAdvice" class="test.aop.AfterAdvice" />
<!-- 配置代理对象 -->
<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean" >
    <!-- 配置代理接口集 -->
    <property name="proxyInterfaces" value="test.aop.ITarget" />
    <!-- 代理目标对象需要实现的接口,可以通过<list>标签设置多个 -->
    <!-- 把通知织入代理对象 -->
    <property name="interceptorNames" >
        <list>
                <idref bean="myBeforeAdvice"/>
                <idref bean="myAfterReturnAdvice"/>
            </list>
    </property><!-- 配置实现了Advice增强接口的Bean,以bean名字进行指定 -->
    <property name="targetName" value="mytarget"></property><!-- 代理的目标对象 -->
</bean>

5. 测试

package test.aop;

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestAOP {

    private ApplicationContext ac;
    @Before
    public void setup(){
        ac = new ClassPathXmlApplicationContext("classpath:test/aop/aop.xml");
    }

    @Test
    public void test(){
        ITarget iTarget = (ITarget) ac.getBean("proxyFactoryBean");
        iTarget.speak(21);
    }
}

测试打印:

前置日志记录: zenghao调用了speak方法,传入参数为:21
hello I’m 21 years old
后置日志记录: zenghao调用了speak方法,返回值为:I’m return value

环绕增强配置

在前面的基础上,我们新增环绕增强类:

package test.aop;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class AroundAdvice implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println(invocation.getArguments()[0] + "——" +
        invocation.getStaticPart() + "——" +
        invocation.getThis().getClass() + "——" +
        invocation.getMethod().getName());
        invocation.proceed();//反射调用目标对象方法
        System.out.println("环绕增强调用结束");
        return "I'm around return value";
    }
}

在aop.xml中类似前置增强增加环绕增强配置,运行测试方法,得到结果:

前置日志记录: zenghao调用了speak方法,传入参数为:21
21——public abstract java.lang.String test.aop.ITarget.speak(java.lang.Integer)——class test.aop.Target——speak
hello I’m 21 years old
环绕增强调用结束
后置日志记录: zenghao调用了speak方法,返回值为:I’m around return value
从以上我们能看到,当同时使用环绕增强和前后置增强时,它们的执行顺序

异常增强配置

常用场景为配置实物管理器,当进行数据库操作的方法发生异常时,可被异常增强捕获,进行失误回滚等操作。一个抛出异常增强的实例如下所示:

package test.aop;

import java.lang.reflect.Method;
import java.sql.SQLException;

import org.springframework.aop.ThrowsAdvice;

public class ExceptionAdvice implements ThrowsAdvice {
    public void AfterThrowing(SQLException e){
        System.out.println(e.getMessage());
    }
    public void AfterThrowing(RuntimeException e){
        System.out.println(e.getMessage());
    }
    public void AfterThrowing(Method method, Object[] args, Object target,SQLException e){
        System.out.println(e.getMessage());
    }
}

其中有几点是需要注意的:
1. 方法名必须为:afterThrowing
2. 三个入参Method method, Object[] args, Object target 要么一起提供,要么都不提供,而最后一个入参必须为Throwable或其子类。当目标对象抛出异常时,增强会调用相似度最高的匹配异常类的方法(在类的继承树上,两个类的距离越近,相似度就越高)

关于引介增强,它可以动态地为类增加新的接口或方法,具有难以想象的动态特性,在后面的学习中我们会再单独提到。

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
1月前
|
Java 开发者 微服务
手写模拟Spring Boot自动配置功能
【11月更文挑战第19天】随着微服务架构的兴起,Spring Boot作为一种快速开发框架,因其简化了Spring应用的初始搭建和开发过程,受到了广大开发者的青睐。自动配置作为Spring Boot的核心特性之一,大大减少了手动配置的工作量,提高了开发效率。
50 0
|
4天前
|
NoSQL Java Redis
Spring Boot 自动配置机制:从原理到自定义
Spring Boot 的自动配置机制通过 `spring.factories` 文件和 `@EnableAutoConfiguration` 注解,根据类路径中的依赖和条件注解自动配置所需的 Bean,大大简化了开发过程。本文深入探讨了自动配置的原理、条件化配置、自定义自动配置以及实际应用案例,帮助开发者更好地理解和利用这一强大特性。
41 14
|
1天前
|
XML Java 数据格式
Spring容器Bean之XML配置方式
通过对以上内容的掌握,开发人员可以灵活地使用Spring的XML配置方式来管理应用程序的Bean,提高代码的模块化和可维护性。
15 6
|
3天前
|
XML Java 数据格式
🌱 深入Spring的心脏:Bean配置的艺术与实践 🌟
本文深入探讨了Spring框架中Bean配置的奥秘,从基本概念到XML配置文件的使用,再到静态工厂方式实例化Bean的详细步骤,通过实际代码示例帮助读者更好地理解和应用Spring的Bean配置。希望对你的Spring开发之旅有所助益。
28 3
|
21天前
|
监控 安全 Java
什么是AOP?如何与Spring Boot一起使用?
什么是AOP?如何与Spring Boot一起使用?
46 5
|
25天前
|
Java 开发者 Spring
深入解析:Spring AOP的底层实现机制
在现代软件开发中,Spring框架的AOP(面向切面编程)功能因其能够有效分离横切关注点(如日志记录、事务管理等)而备受青睐。本文将深入探讨Spring AOP的底层原理,揭示其如何通过动态代理技术实现方法的增强。
52 8
|
25天前
|
Java 开发者 Spring
Spring AOP 底层原理技术分享
Spring AOP(面向切面编程)是Spring框架中一个强大的功能,它允许开发者在不修改业务逻辑代码的情况下,增加额外的功能,如日志记录、事务管理等。本文将深入探讨Spring AOP的底层原理,包括其核心概念、实现方式以及如何与Spring框架协同工作。
|
25天前
|
XML 监控 安全
深入调查研究Spring AOP
【11月更文挑战第15天】
36 5
|
25天前
|
Java 开发者 Spring
Spring AOP深度解析:探秘动态代理与增强逻辑
Spring框架中的AOP(Aspect-Oriented Programming,面向切面编程)功能为开发者提供了一种强大的工具,用以将横切关注点(如日志、事务管理等)与业务逻辑分离。本文将深入探讨Spring AOP的底层原理,包括动态代理机制和增强逻辑的实现。
35 4
|
29天前
|
Java Kotlin 索引
学习Spring框架特性及jiar包下载
Spring 5作为最新版本,更新了JDK基线至8,修订了核心框架,增强了反射和接口功能,支持响应式编程及Kotlin语言,引入了函数式Web框架,并提升了测试功能。Spring框架可在其官网下载,包括文档、jar包和XML Schema文档,适用于Java SE和Java EE项目。
32 0
下一篇
DataWorks