第七章节 spring AOP(下)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 第七章节 spring AOP(下)

2.3.3、 根据切面中的信息创建代理对象

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <!--代理目标-->
    <bean id="newsDAO" class="com.xxxx.spring.dao.impl.NewsDAOImpl"/>
    <bean id="xxxDAO" class="com.xxxx.spring.dao.impl.XXXDAOImpl"/>
    <!--定义前置增强-->
    <bean id="newsDAOAdvice" class="com.xxxx.spring.advice.NewsDAOAdvice"/>
    <!--定义环绕增强-->
    <bean id="newsDAOAroundAdvice" class="com.xxxx.spring.advice.NewsDAOAroundAdvice"/>
    <!--定义切面-->
    <bean id="pointCutAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <!--<property name="patterns" value=".*"/>-->
        <property name="patterns" value="com.xxxx.spring.dao.impl.XXXDAOImpl.insert.*"/>
        <property name="advice" ref="newsDAOAroundAdvice"/>
    </bean>
    <!--根据切面信息创建自动代理-->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
</beans>

3、集成AspectJ

Spring AOP 是一个简化版的 AOP 实现,并没有提供完整版的 AOP 功能。通常情况下,Spring AOP 是能够满足我们日常开发过程中的大多数场景的,但在某些情况下,我们可能需要使用 Spring AOP 范围外的某些 AOP 功能。比如Spring AOP 仅支持执行公共(public)非静态方法的调用作为连接点,如果我们需要向受保护的(protected)或私有的(private)的方法进行增强,此时就需要使用功能更加全面的 AOP 框架来实现,其中使用最多的就是 AspectJ。

3.1、需要导入包

spring-aspects-xxx.jar

aspectjweaver-xxxx.jar

<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>5.3.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.6</version>
</dependency>

3.2、基于XML的AspectJ AOP开发

Spring 提供了基于 XML 的 AOP 支持,并提供了一个名为“aop”的命名空间,该命名空间提供了一个 aop:config 元素。

  • 在 Spring 配置中,所有的切面信息(切面、切点、通知)都必须定义在 aop:config 元素中;
  • 在 Spring 配置中,可以使用多个 aop:config。
  • 每一个 aop:config 元素内可以包含 3 个子元素: pointcut、advisor 和 aspect ,这些子元素必须按照这个顺序进行声明。

3.2.1、xml定义命名空间

增加spring-aop

<?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 
        ">
</beans>

3.2.2、定义切面

<aop:config>
    <aop:aspect id="myAspect" ref="myBean"/>
</aop:config>

3.2.3、定义切入点

execution 的语法格式格式为:

execution([权限修饰符] [返回值类型] [类的完全限定名] [方法名称]([参数列表]) 其中:

  • 返回值类型、方法名、参数列表是必须配置的选项,而其它参数则为可选配置项。
  • 返回值类型:*表示可以为任何返回值。如果返回值为对象,则需指定全路径的类名。
  • 类的完全限定名:指定包名 + 类名。
  • 方法名:*代表所有方法,set* 代表以 set 开头的所有方法。
  • 参数列表:
    (…)代表所有参数;
    (*)代表只有一个参数,参数类型为任意类型;
    (*,String)代表有两个参数,第一个参数可以为任何值,第二个为 String 类型的值。

3.2.4、定义通知

<!-- 前置通知 -->
    <aop:before pointcut-ref="myPointCut" method="..."/>   
    <!-- 后置通知 -->
    <aop:after-returning pointcut-ref="myPointCut" method="..."/>
    <!-- 环绕通知 -->
    <aop:around pointcut-ref="myPointCut" method="..."/>
    <!-- 异常通知 -->
    <aop:after-throwing pointcut-ref="myPointCut" method="..."/>
    <!-- 最终通知 -->
    <aop:after pointcut-ref="myPointCut" method="..."/>

列子:

/**
 * 新闻信息服务接口
 */
public interface NewsDAO {
    void insert();
    void delete();
    void update();
    void select();
}
public class NewsDAOImpl implements NewsDAO {
    @Override
    public void insert() {
        System.out.println("执行UserDAOImpl的insert()方法");
    }
    @Override
    public void delete() {
        System.out.println("执行UserDAOImpl的delete()方法");
        //throw new RuntimeException("ddd");
    }
    @Override
    public void update() {
        System.out.println("执行UserDAOImpl的update()方法");
    }
    @Override
    public void select() {
        System.out.println("执行UserDAOImpl的select()方法");
    }
}

定义Apect类

public class NewsAspect {
    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 afterThrow(Throwable exception) {
        System.out.println("异常增强…… 异常信息为:" + exception.getMessage());
    }
    public void afterReturning(Object returnValue) {
        System.out.println("后置返回增强…… 方法返回值为:" + returnValue);
    }
}

定义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="newsDAO" class="com.xxxx.spring.dao.impl.NewsDAOImpl"/>
    <!--定义切面-->
    <bean id="newsAspect" class="com.xxxx.spring.advice.NewsAspect"/>
    <aop:config>
        <!--定义切点-->
        <aop:pointcut id="beforePointCut" expression="execution(* com.xxxx.spring.dao.NewsDAO.insert(..))"/>
        <aop:pointcut id="throwPointCut" expression="execution(* com.xxxx.spring.dao.NewsDAO.update(..))"/>
        <aop:pointcut id="afterRerturningPointCut" expression="execution(* com.xxxx.spring.dao.NewsDAO.delete(..))"/>
        <aop:pointcut id="afterPointCut" expression="execution(* com.xxxx.spring.dao.NewsDAO.select(..))"/>
        <aop:pointcut id="aroundPointCut" expression="execution(* com.xxxx.spring.dao.NewsDAO.update(..))"/>
        <aop:aspect  ref="newsAspect">
            <aop:before method="before" pointcut-ref="beforePointCut"/>
            <aop:after-throwing method="afterThrow" pointcut-ref="throwPointCut" throwing="exception"/>
            <aop:after-returning method="afterReturning" pointcut-ref="afterRerturningPointCut" returning="returnValue"/>
            <aop:after method="after" pointcut-ref="afterPointCut"/>
            <aop:around method="around" pointcut-ref="aroundPointCut"/>
        </aop:aspect>
    </aop:config>
</beans>

3.3、基于注解的AspectJ AOP开发

AspectJ 框架为 AOP 开发提供了一套 @AspectJ 注解。它允许我们直接在 Java 类中通过注解的方式对切面(Aspect)、切入点(Pointcut)和增强(Advice)进行定义。

名称 说明
@Aspect 用于定义一个切面。
@Pointcut 用于定义一个切入点。
@Before 用于定义前置通知,相当于 BeforeAdvice。
@AfterReturning 用于定义后置通知,相当于 AfterReturningAdvice。
@Around 用于定义环绕通知,相当于 MethodInterceptor。
@AfterThrowing 用于定义抛出通知,相当于 ThrowAdvice。
@After 用于定义最终通知,不管是否异常,该通知都会执行。
@DeclareParents 用于定义引介通知,相当于 IntroductionInterceptor

3.3.1、启用@AspectJ注解

Java配置类或者XML配置启用

3.3.1.1、Java配置类

@Configuration
@ComponentScan(basePackages = "com.xxxx.spring")
@EnableAspectJAutoProxy
public class AppConfig {
}

3.3.1.2、XML配置

<!-- 开启注解扫描 -->
<context:component-scan base-package="com.xxxx.spring">
</context:component-scan>
<!--开启AspectJ 自动代理-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

3.3.2、定义切面

@Component
@Aspect
public class NewsAspect {
    @Pointcut(value = "execution(* com.xxxx.spring.dao.NewsDAO.insert(..))")
    public void beforePointCut(){
    }
    @Before(value = "NewsAspect.beforePointCut()")
    public void before() {
        System.out.println("前置增强……");
    }
    @After(value = "execution(* com.xxxx.spring.dao.NewsDAO.select(..))")
    public void after() {
        System.out.println("最终增强……");
    }
    @Around(value="execution(* com.xxxx.spring.dao.NewsDAO.update(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println(proceedingJoinPoint.getSignature().getName());
        System.out.println("环绕增强---前……");
        proceedingJoinPoint.proceed();
        System.out.println("环绕增强---后……");
    }
    @AfterThrowing(value = "execution(* com.xxxx.spring.dao.NewsDAO.update(..))",throwing = "exception")
    public void afterThrow(Throwable exception) {
        System.out.println("异常增强…… 异常信息为:" + exception.getMessage());
    }
    @AfterReturning(value = "execution(* com.xxxx.spring.dao.NewsDAO.update(..))",returning = "returnValue")
    public void afterReturning(Object returnValue) {
        System.out.println("后置返回增强…… 方法返回值为:" + returnValue);
    }
}

3.3.3、运行

public class Test05 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
        NewsDAO newsDAO = annotationConfigApplicationContext.getBean("newsDAO", NewsDAO.class);
        newsDAO.update();
    }
}

4、aop实战练习

定义日志框架

1、src下面增加log.properties

log.file  //日志存放的位置
 log.format //日志格式
 log.level=DEBUG //日志等级    DEBUG/INFO/WARN/ERROR   
 log.target=console,file #日志输出

2、定义一个类,读取第一步的配置文件

3、定义一个日志生成类 XXXX

根据第二步读到配置内容,执行日志的生成逻辑
 提供四个方法:debug、info、warn、error


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
1月前
|
XML Java 数据安全/隐私保护
Spring Aop该如何使用
本文介绍了AOP(面向切面编程)的基本概念和术语,并通过具体业务场景演示了如何在Spring框架中使用Spring AOP。文章详细解释了切面、连接点、通知、切点等关键术语,并提供了完整的示例代码,帮助读者轻松理解和应用Spring AOP。
Spring Aop该如何使用
|
17天前
|
监控 安全 Java
什么是AOP?如何与Spring Boot一起使用?
什么是AOP?如何与Spring Boot一起使用?
43 5
|
22天前
|
Java 开发者 Spring
深入解析:Spring AOP的底层实现机制
在现代软件开发中,Spring框架的AOP(面向切面编程)功能因其能够有效分离横切关注点(如日志记录、事务管理等)而备受青睐。本文将深入探讨Spring AOP的底层原理,揭示其如何通过动态代理技术实现方法的增强。
49 8
|
22天前
|
Java 开发者 Spring
Spring AOP 底层原理技术分享
Spring AOP(面向切面编程)是Spring框架中一个强大的功能,它允许开发者在不修改业务逻辑代码的情况下,增加额外的功能,如日志记录、事务管理等。本文将深入探讨Spring AOP的底层原理,包括其核心概念、实现方式以及如何与Spring框架协同工作。
|
22天前
|
XML 监控 安全
深入调查研究Spring AOP
【11月更文挑战第15天】
34 5
|
22天前
|
Java 开发者 Spring
Spring AOP深度解析:探秘动态代理与增强逻辑
Spring框架中的AOP(Aspect-Oriented Programming,面向切面编程)功能为开发者提供了一种强大的工具,用以将横切关注点(如日志、事务管理等)与业务逻辑分离。本文将深入探讨Spring AOP的底层原理,包括动态代理机制和增强逻辑的实现。
32 4
|
2月前
|
存储 缓存 Java
Spring高手之路23——AOP触发机制与代理逻辑的执行
本篇文章深入解析了Spring AOP代理的触发机制和执行流程,从源码角度详细讲解了Bean如何被AOP代理,包括代理对象的创建、配置与执行逻辑,帮助读者全面掌握Spring AOP的核心技术。
48 3
Spring高手之路23——AOP触发机制与代理逻辑的执行
|
1月前
|
Java Spring
[Spring]aop的配置与使用
本文介绍了AOP(面向切面编程)的基本概念和核心思想。AOP是Spring框架的核心功能之一,通过动态代理在不修改原代码的情况下注入新功能。文章详细解释了连接点、切入点、通知、切面等关键概念,并列举了前置通知、后置通知、最终通知、异常通知和环绕通知五种通知类型。
34 1
|
1月前
|
安全 Java 测试技术
Java开发必读,谈谈对Spring IOC与AOP的理解
Spring的IOC和AOP机制通过依赖注入和横切关注点的分离,大大提高了代码的模块化和可维护性。IOC使得对象的创建和管理变得灵活可控,降低了对象之间的耦合度;AOP则通过动态代理机制实现了横切关注点的集中管理,减少了重复代码。理解和掌握这两个核心概念,是高效使用Spring框架的关键。希望本文对你深入理解Spring的IOC和AOP有所帮助。
36 0
|
3月前
|
设计模式 Java 测试技术
spring复习04,静态代理动态代理,AOP
这篇文章讲解了Java代理模式的相关知识,包括静态代理和动态代理(JDK动态代理和CGLIB),以及AOP(面向切面编程)的概念和在Spring框架中的应用。文章还提供了详细的示例代码,演示了如何使用Spring AOP进行方法增强和代理对象的创建。
spring复习04,静态代理动态代理,AOP