Spring5源码(31)-基于@AspectJ的AOP

简介: Spring5源码(31)-基于@AspectJ的AOP


上一节介绍了基于Schema的AOP,本篇介绍基于@AspectJ的AOP。

1.@AspectJ切面
  • 目标对象

package com.lyc.cn.v2.day07;
public interface Animal {
    void sayHello();
}

package com.lyc.cn.v2.day07;
public class Dog implements Animal {
    public void sayHello() {
        System.out.println("--被增强的方法");
    }
}
  • 引介

package com.lyc.cn.v2.day07;
public interface IIntroduce {
    void sayIntroduce();
}

package com.lyc.cn.v2.day07;
public class IntroduceImpl implements IIntroduce {
    @Override
    public void sayIntroduce() {
        System.out.println("--引入");
    }
}
  • 切面

package com.lyc.cn.v2.day07;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
/**
 * 切面类
 * @author: LiYanChao
 * @create: 2018-10-31 15:46
 */
@Aspect
public class DogAspect {
    /**
     * 例如:execution (* com.sample.service.impl..*.*(..)
     * 1、execution(): 表达式主体。
     * 2、第一个*号:表示返回类型,*号表示所有的类型。
     * 3、包名:表示需要拦截的包名,后面的两个点表示当前包和当前包的所有子包,
     * 即com.sample.service.impl包、子孙包下所有类的方法。
     * 4、第二个*号:表示类名,*号表示所有的类。
     * 5、*(..):最后这个星号表示方法名,*号表示所有的方法,后面括弧里面表示方法的参数,两个点表示任何参数。
     **/
    @Pointcut("execution(* com.lyc.cn.v2.day07.*.*(..))")
    public void test() {
    }
    @Before("test()")
    public void beforeTest() {
        System.out.println("==前置增强");
    }
    @After("test()")
    public void afterTest() {
        System.out.println("==后置最终增强");
    }
    @AfterThrowing("test()")
    public void afterThrowingTest() {
        System.out.println("==后置异常增强");
    }
    @AfterReturning("test()")
    public void afterReturningTest() {
        System.out.println("==后置返回增强");
    }
    @Around("test()")
    public Object aroundTest(ProceedingJoinPoint p) {
        System.out.println("==环绕增强开始");
        Object o = null;
        try {
            o = p.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
        }
        System.out.println("==环绕增强结束");
        return o;
    }
    @DeclareParents(value = "com.lyc.cn.v2.day07.Dog", defaultImpl = IntroduceImpl.class)
    private IIntroduce iIntroduce;
}
  • 配置文件

<?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.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--
        1、proxy-target-class
            如果被代理的目标对象至少实现了一个接口,则会使用JDK动态代理,所有实现该目标类实现的接口都将被代理
            如果该目标对象没有实现任何接口,则创建CGLIB动态代理。
            但是可以通过proxy-target-class属性强制指定使用CGLIB代理,
        2、expose-proxy
            解决目标对象内部的自我调用无法实施切面增强的问题
    -->
    <aop:aspectj-autoproxy proxy-target-class="true">
        <!-- 指定@Aspect类,支持正则表达式,符合该表达式的切面类才会被应用-->
        <aop:include name="dogAspect"></aop:include>
    </aop:aspectj-autoproxy>
    <!--bean-->
    <bean id="dog" class="com.lyc.cn.v2.day07.Dog"/>
    <!--AspectJ-->
    <bean name="dogAspect" class="com.lyc.cn.v2.day07.DogAspect"/>
</beans>
  • 测试及结果

package com.lyc.cn.v2.day07;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
    @Test
    public void test1() {
        // 基于@AspectJ注解方式
        ApplicationContext ctx = new ClassPathXmlApplicationContext("v2/day07.xml");
        Dog dog = ctx.getBean("dog", Dog.class);
        dog.sayHello();
    }
    @Test
    public void test2() {
        // 引入
        ApplicationContext ctx = new ClassPathXmlApplicationContext("v2/day07.xml");
        // 注意:getBean获取的是dog
        IIntroduce introduce = ctx.getBean("dog", IIntroduce.class);
        introduce.sayIntroduce();
    }
}

// 测试一
==环绕增强开始
==前置增强
--被增强的方法
==环绕增强结束
==后置最终增强
==后置返回增强

// 测试二
--引入
2.总结

前篇和本篇主要还是回顾了SpringAop的使用方式,也为了接下来的源码分析做好测试类准备,在接下来的分析中主要讲解以@AspectJ方式的实现方式。



目录
相关文章
|
4月前
|
XML 安全 Java
使用 Spring 的 @Aspect 和 @Pointcut 注解简化面向方面的编程 (AOP)
面向方面编程(AOP)通过分离横切关注点,如日志、安全和事务,提升代码模块化与可维护性。Spring 提供了对 AOP 的强大支持,核心注解 `@Aspect` 和 `@Pointcut` 使得定义切面与切入点变得简洁直观。`@Aspect` 标记切面类,集中处理通用逻辑;`@Pointcut` 则通过表达式定义通知的应用位置,提高代码可读性与复用性。二者结合,使开发者能清晰划分业务逻辑与辅助功能,简化维护并提升系统灵活性。Spring AOP 借助代理机制实现运行时织入,与 Spring 容器无缝集成,支持依赖注入与声明式配置,是构建清晰、高内聚应用的理想选择。
572 0
|
3月前
|
XML Java 数据格式
《深入理解Spring》:AOP面向切面编程深度解析
Spring AOP通过代理模式实现面向切面编程,将日志、事务等横切关注点与业务逻辑分离。支持注解、XML和编程式配置,提供五种通知类型及丰富切点表达式,助力构建高内聚、低耦合的可维护系统。
|
8月前
|
监控 安全 Java
Spring AOP实现原理
本内容主要介绍了Spring AOP的核心概念、实现机制及代理生成流程。涵盖切面(Aspect)、连接点(Join Point)、通知(Advice)、切点(Pointcut)等关键概念,解析了JDK动态代理与CGLIB代理的原理及对比,并深入探讨了通知执行链路和责任链模式的应用。同时,详细分析了AspectJ注解驱动的AOP解析过程,包括切面识别、切点表达式匹配及通知适配为Advice的机制,帮助理解Spring AOP的工作原理与实现细节。
1313 13
|
5月前
|
人工智能 监控 安全
如何快速上手【Spring AOP】?核心应用实战(上篇)
哈喽大家好吖~欢迎来到Spring AOP系列教程的上篇 - 应用篇。在本篇,我们将专注于Spring AOP的实际应用,通过具体的代码示例和场景分析,帮助大家掌握AOP的使用方法和技巧。而在后续的下篇中,我们将深入探讨Spring AOP的实现原理和底层机制。 AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架中的核心特性之一,它能够帮助我们解决横切关注点(如日志记录、性能统计、安全控制、事务管理等)的问题,提高代码的模块化程度和复用性。
|
5月前
|
设计模式 Java 开发者
如何快速上手【Spring AOP】?从动态代理到源码剖析(下篇)
Spring AOP的实现本质上依赖于代理模式这一经典设计模式。代理模式通过引入代理对象作为目标对象的中间层,实现了对目标对象访问的控制与增强,其核心价值在于解耦核心业务逻辑与横切关注点。在框架设计中,这种模式广泛用于实现功能扩展(如远程调用、延迟加载)、行为拦截(如权限校验、异常处理)等场景,为系统提供了更高的灵活性和可维护性。
|
3月前
|
监控 Java Spring
AOP 切面编程
AOP(面向切面编程)通过动态代理在不修改源码的前提下,对方法进行增强。核心概念包括连接点、通知、切入点、切面和目标对象。常用于日志记录、权限校验、性能监控等场景,结合Spring AOP与@Aspect、@Pointcut等注解,实现灵活的横切逻辑管理。
598 6
AOP 切面编程
|
5月前
|
监控 Java Spring
AOP切面编程快速入门
AOP(面向切面编程)通过分离共性逻辑,简化代码、减少冗余。它通过切点匹配目标方法,在不修改原方法的前提下实现功能增强,如日志记录、性能监控等。核心概念包括:连接点、通知、切入点、切面和目标对象。Spring AOP支持多种通知类型,如前置、后置、环绕、返回后、异常通知,灵活控制方法执行流程。通过@Pointcut可复用切点表达式,提升维护性。此外,结合自定义注解,可实现更清晰的切面控制。
517 5
Micronaut AOP与代理机制:实现应用功能增强,无需侵入式编程的秘诀
AOP(面向切面编程)能够帮助我们在不修改现有代码的前提下,为应用程序添加新的功能或行为。Micronaut框架中的AOP模块通过动态代理机制实现了这一目标。AOP将横切关注点(如日志记录、事务管理等)从业务逻辑中分离出来,提高模块化程度。在Micronaut中,带有特定注解的类会在启动时生成代理对象,在运行时拦截方法调用并执行额外逻辑。例如,可以通过创建切面类并在目标类上添加注解来记录方法调用信息,从而在不侵入原有代码的情况下增强应用功能,提高代码的可维护性和可扩展性。
325 1