Spring AOP 的三种使用方式(万字长文)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 前言Spring AOP 作为 Spring Framework 的核心模块,对 Spring IOC 加以补充,Spring 内部使用它提供了企业级的服务,如事务、异步、缓存等,同时它也允许用户自定义 Aspect,以便用 AOP 补充对 OOP 的使用。通常情况下,我们会通过 AspectJ 的注解来使用 Spring AOP,那么 Spring 一共提供了哪些使用 AOP 的方式呢?本篇将对其总结,并尝试了解 Spring AOP 的内部实现。

前言


Spring AOP 作为 Spring Framework 的核心模块,对 Spring IOC 加以补充,Spring 内部使用它提供了企业级的服务,如事务、异步、缓存等,同时它也允许用户自定义 Aspect,以便用 AOP 补充对 OOP 的使用。通常情况下,我们会通过 AspectJ 的注解来使用 Spring AOP,那么 Spring 一共提供了哪些使用 AOP 的方式呢?本篇将对其总结,并尝试了解 Spring AOP 的内部实现。


Spring AOP 使用方式


Spring 作为一个广为流行的 Java 框架,主要提供了三种使用方式。


注解:将注解作为元数据,Spring IOC 容器运行时对指定类路径的类进行扫描,根据不同注解执行不同的行为。

外部化配置:和注解类似,将 xml 或 properties 文件内容作为元数据,Spring IOC 容器运行时对配置进行读取。

API:这是 Spring 底层暴露给用户可以直接使用的 API ,通常来说使用较少。

Spring AOP 的使用方式也无外乎这三种,AOP 基于代理,如果正在阅读的小伙伴对代理和AOP基本概念不熟悉可以先阅读我前面的文章《Java 中创建代理的几种方式》和《从代理到AOP,如何手写一个AOP框架》,下面对 Spring AOP 的几种使用方式具体介绍。


注解


随着 JDK 5 注解新特性的添加,Spring 也对其进行了支持,由于注解天然和 Java 结合,可以省去大量的外部化配置,因此在Spring 中注解已经成为主流使用方式。


Spring AOP 的目标不是为了实现完整的 AOP 框架,它和 IOC 容器整合才能最大发挥其作用。Spring 的开发者认为 Spring AOP 和 AspectJ 是互补关系而不是竞争关系,由于 AspectJ 已经很优秀了,因此 Spring 对并未提出新的注解,而是直接对 AspectJ 中的注解进行了有限的支持,可以将 AspectJ 框架中的注解直接应用于 Spring 。


0. 场景


假定我们需要通过 Spring AOP 打印如下方法的参数和返回值。


public interface IService {
    String doSomething(String param);
}
@Service
public class ServiceImpl implements IService {
    @Override
    public String doSomething(String param) {
        return "param is : " + param;
    }
}


1. 依赖引入


在 Spring Framework 环境下,使用 AspectJ 注解需要分别引用如下两个依赖。


        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.3</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.6</version>
        </dependency>


2. 启用 AspectJ 支持


引入所需依赖之后我们还需要显式的开启对 AspectJ 的支持,这需要在配置类上添加 @EnableAspectJAutoProxy 注解。在 SpringBoot 环境下会自动配置,因此无需添加。

@Configuration
@EnableAspectJAutoProxy
public class App {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext("com.zzuhkp.blog.aop");
        IService service = applicationContext.getBean(IService.class);
        service.doSomething("hello,aop");
        applicationContext.close();
    }
}


3. Aspect 定义


必要的工作都准备之后,我们就可以通过注解定义 Aspect ,将我们打印日志的逻辑全部放到这个 Aspect 中。在普通的类上加上 @Aspect 注解,这个类就成为一个 Aspect 了,除此之外由于 Spring 只会对 Bean 上的 @Aspect 注解处理,因此还需要将这个 Aspect 声明为 Spring 的一个 Bean。


@Component
@Aspect
public class LogAspect {
}


4. Pointcut 定义


@Aspect 主要用于将 Pointcut、Advice 整合到一个类中。有了 Aspect 之后,我们就可以在这个 Aspect 中定义 Pointcut 。


通常情况下,我们可以在 Aspect 类中定义一个权限修饰符为 private 类型、无参的空方法,在方法上添加 @Pointcut 注解将这个方法指定为一个 Pointcut,其中方法名作为 Pointcut 的名称,这样在 Advice 中通过这个方法名就可以复用这个 Pointcut。


@Component
@Aspect
public class LogAspect {
    @Pointcut(value = "execution(* *(..))")
    private void pointcut() {
    }
}    


上述代码定义了一个名为 pointcut 的 Pointcut,@Pointcut 注解中的表达式表示 Spring AOP 会拦截所有 bean 的所有方法的执行。


5. Advice 定义


Pointcut 用于指定拦截哪些方法,拦截这些方法后执行哪些动作由 Advice 来确定。


AspectJ 将 Advice 分为三类,分别是 before、after、around,分别表示目标方法执行前、执行后、执行前后执行 Advice。


after 又可以细分为 after、after returning、after throwing。after 表示无论目标方法是否抛出异常都会执行 Advice;after returning 表示目标方法正常返回才会执行 Advice;after throwing 表示目标方法抛出异常才会执行 Advice;这三种 after Spring 是通过 try{} catch(exception){} finally{} 来实现的。


Spring 中的 Advice 通过也是通过方法来定义,通过在方法上添加不同类型的 Advice 注解来表示这个方法是一个 Advice 方法。


先看我们对 Advice 的定义。


@Slf4j
@Component
@Aspect
public class LogAspect {
    @Pointcut(value = "execution(* *(..))")
    private void pointcut() {
    }
    @Before(value = "pointcut() && args(param))", argNames = "param")
    public void before(String param) {
        log.info("before,param is:[{}]", param);
    }
    @After("pointcut()")
    public void after(JoinPoint joinPoint) {
        log.info("after:[{}]", joinPoint.getSignature());
    }
    @AfterReturning(value = "pointcut() && args(param)", argNames = "param,result", returning = "result")
    public void afterReturning(String param, String result) {
        log.info("after returning,param is:[{}],result is:[{}],", param, result);
    }
    @AfterThrowing(value = "pointcut()", throwing = "throwable")
    public void afterThrowing(Throwable throwable) {
        log.warn("after throwing", throwable);
    }
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("around before,param is:[{}]", joinPoint.getArgs());
        Object result = joinPoint.proceed();
        log.info("around after,result is:[{}]", result);
        return result;
    }
}


关于 AspectJ 中的 Advice ,可以总结如下约定。


所有的 Advice 注解都需要指定 value 属性,值为 Pointcut 表达式,用以确定拦截的方法,这个表达式可以是对 Pointcut 的引用,如 @After("pointcut()")。

Advice 方法可以有一些参数,这些参数需要在注解中的 argNames 属性按照顺序指定参数名称,以便在 Pointcut 表达式中引用。如 @AfterReturning(value = "pointcut() && args(param)", argNames = "param,result", returning = "result")。参数可选类型如下:

参数可以为目标方法的参数,用以接收目标方法参数。

参数可以为 JoinPoint、JoinPoint.StaticPart,对于 around 类型的 Advice 方法参数还可以为 ProceedingJoinPoint 以便调用目标方法,如果这些参数在第一个位置还可以在 argNames 中省略这几个参数的名称。

对于 after returing 类型的 Advice,参数可以为目标方法返回值类型,此时需要通过注解属性 returning 指定目标方法返回值在 Advice 方法中的参数名称。

对于 after throwing 类型的 Advice,参数可以为目标方法抛出的异常类型,此时需要通过注解属性 throwing 指定目标方法抛出的异常在 Advice 方法中的参数名称。

执行测试代码后打印的日志如下。


11:28:18.982 [main] INFO com.zzuhkp.blog.aop.LogAspect - around before,param is:[hello,aop]
11:28:18.986 [main] INFO com.zzuhkp.blog.aop.LogAspect - before,param is:[hello,aop]
11:28:18.986 [main] INFO com.zzuhkp.blog.aop.LogAspect - after returning,param is:[hello,aop],result is:[param is : hello,aop],
11:28:18.988 [main] INFO com.zzuhkp.blog.aop.LogAspect - after:[String com.zzuhkp.blog.aop.IService.doSomething(String)]
11:28:18.988 [main] INFO com.zzuhkp.blog.aop.LogAspect - around after,result is:[param is : hello,aop]


说明不同类型的 Advice 执行顺序如下:around、before、after returning、after、around。around 打印两次则是因为 around 类型的 advice 在目标方法执行前后都添加了打印逻辑,这还可以看出 Spring 为目标类创建了多层代理。


对于同一个 Aspect 中的同一种 advice,如果想指定执行顺序还可以在 advice 方法上添加 @Order 注解,对于不同 Aspect 中的 Advice ,如果想指定顺序,需要在 Aspect 类上添加 @Order 注解或实现 Ordered 方法。


外部化配置


Spring 使用的外部化配置文件主要是 xml 和 properties,在注解出现之前,Spring 主要使用 xml 配置 bean,将上述 Aspect 注解转换为 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"
       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/context https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
    <bean id="service" class="com.zzuhkp.blog.aop.ServiceImpl"/>
    <bean id="logAspect" class="com.zzuhkp.blog.aop.LogAspect"/>
    <aop:config>
        <aop:aspect ref="logAspect">
            <aop:pointcut id="pointcut" expression="execution(* *(..))"/>
            <aop:around method="around" pointcut-ref="pointcut"/>
            <aop:before method="before" pointcut="execution(* *(..)) and args(param)" arg-names="param"/>
            <aop:after-returning method="afterReturning" pointcut="execution(* *(..)) and args(param)"
                                 arg-names="param,result" returning="result"/>
            <aop:after method="after" pointcut-ref="pointcut"/>
            <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" arg-names="throwable" throwing="throwable"/>
        </aop:aspect>
    </aop:config>
</beans>


修改测试代码。


public class App {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("context-aop.xml");
        applicationContext.refresh();
        IService service = applicationContext.getBean(IService.class);
        service.doSomething("hello,aop");
        applicationContext.close();
    }
}


执行结果如下。


13:41:59.881 [main] INFO com.zzuhkp.blog.aop.LogAspect - around before,param is:[hello,aop]
13:41:59.883 [main] INFO com.zzuhkp.blog.aop.LogAspect - before,param is:[hello,aop]
13:41:59.883 [main] INFO com.zzuhkp.blog.aop.LogAspect - around after,result is:[param is : hello,aop]
13:41:59.883 [main] INFO com.zzuhkp.blog.aop.LogAspect - after returning,param is:[hello,aop],result is:[param is : hello,aop],
13:41:59.884 [main] INFO com.zzuhkp.blog.aop.LogAspect - after:[String com.zzuhkp.blog.aop.IService.doSomething(String)]


使用 xml 配置之后,虽然 before advice 在 after advice 之前执行,但是 around 类型的 advice 和其他 advice 类型执行的顺序和注解有所不同,需要加以留意。


API


上述通过注解和 XML 方式的形式配置 Aspect,Spring 会在 bean 的生命周期自动创建代理,对 Spring Bean 生命周期感兴趣的小伙伴可以参考我前面文章《Java 面试必备的 Spring Bean 生命周期总结》。除此之外,Spring 还提供了手动通过 API 创建代理对象的方式,这种方式不依赖于 Spring 容器,不依赖 AspectJ,需要对 Spring AOP 底层 API 较为熟悉才能使用。参照上面的样例,我们再次用 API 的方式实现如下。


@Slf4j
public class App {
    public static void main(String[] args) {
        Pointcut pointcut = new StaticMethodMatcherPointcut() {
            @Override
            public boolean matches(Method method, Class<?> targetClass) {
                return method.getDeclaringClass() == IService.class &&
                        "doSomething".equals(method.getName()) &&
                        method.getParameterCount() == 1 && method.getParameterTypes()[0] == String.class;
            }
        };
        IService service = new ServiceImpl();
        ProxyFactory proxyFactory = new ProxyFactory(service);
        proxyFactory.addAdvisor(new DefaultPointcutAdvisor(pointcut, new MethodBeforeAdvice() {
            @Override
            public void before(Method method, Object[] args, Object target) throws Throwable {
                log.info("before,param is:[{}]", args[0]);
            }
        }));
        proxyFactory.addAdvisor(new DefaultPointcutAdvisor(pointcut, new AfterReturningAdvice() {
            @Override
            public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
                log.info("after returning,param is:[{}],result is:[{}],", args[0], returnValue);
            }
        }));
        class CustomThrowsAdvice implements ThrowsAdvice {
            public void afterThrowing(Throwable throwable) {
                log.warn("after throwing", throwable);
            }
        }
        proxyFactory.addAdvisor(new DefaultPointcutAdvisor(pointcut, new CustomThrowsAdvice()));
        proxyFactory.addAdvice(new MethodInterceptor() {
            @Override
            public Object invoke(MethodInvocation invocation) throws Throwable {
                log.info("around before,param is:[{}]", invocation.getArguments());
                Object result = invocation.proceed();
                log.info("around after,result is:[{}]", result);
                return result;
            }
        });
        IService proxy = (IService) proxyFactory.getProxy();
        proxy.doSomething("hello,aop");
    }
}


PrxoyFactory 是 Spring 提供给我们用于创建代理的核心类,我们创建了 IService 的代理,然后添加了一些 PointcutAdvisor,Advisor 是 Advice 的容器,PointcutAdvisor 还可以指定哪些 Pointcut 满足后执行 Advice,同时我们还添加了 MethodInterceptor 用于表示 around advice,这同样也是 Spring 实现各种 Advice 的基础。关于 Spring AOP,我这里总结了一个思维导图给大家参考,感兴趣的可以点击查看大图。


3.png

上述示例打印结果如下。

14:57:04.924 [main] INFO com.zzuhkp.blog.aop.App - before,param is:[hello,aop]
14:57:04.926 [main] INFO com.zzuhkp.blog.aop.App - around before,param is:[hello,aop]
14:57:04.926 [main] INFO com.zzuhkp.blog.aop.App - around after,result is:[param is : hello,aop]
14:57:04.926 [main] INFO com.zzuhkp.blog.aop.App - after returning,param is:[hello,aop],result is:[param is : hello,aop],


这里的 Advice 顺序同样与注解有所不同,需要注意。


非常规操作


上述示例中,注解和 XML 配置属于容器自动创建代理,而通过 API 变成的方式则属于手动创建代理,相对来说还属于比较常规的操作。下面简单介绍一些 Spring 中和容器整合的不常用的非常规操作,不感兴趣的小伙伴可以跳过。


自动代理创建


前面内容,我们通过 @EnableAspectJAutoProxy 开启了对 AspectJ 注解的支持,Spring 容器会在 Bean 的生命周期创建代理,底层是创建了一个类型为 AnnotationAwareAspectJAutoProxyCreator 的 bean,在 Spring 的事务管理中则会创建一个类型为 InfrastructureAdvisorAutoProxyCreator 的 bean,它们的实现方式类似。


除了上面两个 Spring 内部使用的用于自动创建代理的 bean,Spring 还预留了两个类给用户使用,将这两个类声明为 bean 即可,这两个类分别如下。


BeanNameAutoProxyCreator :可以指定需要创建代理的 bean,不能指定自定义 Advice,能力有限。

DefaultAdvisorAutoProxyCreator:使用容器中的 Advisor bean 为其他 bean 创建代理。

我们利用 DefaultAdvisorAutoProxyCreator 再次实现日志打印的 AOP。


Pointcut 代码如下。


public class CustomPointcut extends StaticMethodMatcherPointcut {
    @Override
    public boolean matches(Method method, Class<?> targetClass) {
        return method.getDeclaringClass() == IService.class &&
                "doSomething".equals(method.getName()) &&
                method.getParameterCount() == 1 && method.getParameterTypes()[0] == String.class;
    }
}


用于实现 Before Advice 的代码如下。


@Slf4j
@Data
public class CustomBeforeAdvisor implements PointcutAdvisor {
    @Autowired
    private CustomPointcut pointcut;
    @Override
    public Pointcut getPointcut() {
        return pointcut;
    }
    @Override
    public Advice getAdvice() {
        return new MethodBeforeAdvice() {
            @Override
            public void before(Method method, Object[] args, Object target) throws Throwable {
                log.info("before,param is:[{}]", args[0]);
            }
        };
    }
    @Override
    public boolean isPerInstance() {
        return false;
    }
}


用于实现 After Advice 的 Advisor 代码如下。


@Slf4j
@Data
public class CustomAfterReturningAdvisor implements PointcutAdvisor {
    @Autowired
    private CustomPointcut pointcut;
    @Override
    public Pointcut getPointcut() {
        return pointcut;
    }
    @Override
    public Advice getAdvice() {
        return new AfterReturningAdvice() {
            @Override
            public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
                log.info("after returning,param is:[{}],result is:[{}]", args[0], returnValue);
            }
        };
    }
    @Override
    public boolean isPerInstance() {
        return false;
    }
}


测试代码如下。


@Slf4j
public class App {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(ServiceImpl.class, CustomPointcut.class, CustomBeforeAdvisor.class, CustomAfterReturningAdvisor.class,
                DefaultAdvisorAutoProxyCreator.class
        );
        context.refresh();
        IService service = context.getBean(IService.class);
        service.doSomething("hello,aop");
        context.close();
    }
}


为了简化篇幅,我们仅实现了 Before Advice 和 After Advice,日志打印如下。


15:44:15.081 [main] INFO com.zzuhkp.blog.aop.CustomBeforeAdvisor - before,param is:[hello,aop]
15:44:15.082 [main] INFO com.zzuhkp.blog.aop.CustomAfterReturningAdvisor - after returning,param is:[hello,aop],result is:[param is : hello,aop]


表示通过 DefaultAdvisorAutoProxyCreator 实现了我们的需求,这种方式创建了大量的类,并且需要对 Spring API 有一定的了解才能使用,因此实际使用场景较少。


手动代理创建


除了通过 DefaultAdvisorAutoProxyCreator 自动创建代理,我们还可以通过 ProxyFactoryBean 手动为单个 bean 对象创建代理。


我们在上述的样例代码中继续修改,修改 Spring 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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="service" class="com.zzuhkp.blog.aop.ServiceImpl"/>
    <bean id="pointcut" class="com.zzuhkp.blog.aop.CustomPointcut"/>
    <bean id="beforeAdvisor" class="com.zzuhkp.blog.aop.CustomBeforeAdvisor">
        <property name="pointcut" ref="pointcut"/>
    </bean>
    <bean id="afterAdvisor" class="com.zzuhkp.blog.aop.CustomAfterReturningAdvisor">
        <property name="pointcut" ref="pointcut"/>
    </bean>
    <bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="targetName" value="service"/>
        <property name="interceptorNames" value="beforeAdvisor,afterAdvisor"/>
    </bean>
</beans>

使用 ProxyFactoryBean 创建代理,需要使用 targetName 指定目标 bean 的名称,使用 interceptorNames 指定 Advisor bean 的名称。继续修改测试代码。


public class App {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("context-aop.xml");
        IService service = context.getBean("serviceProxy",IService.class);
        service.doSomething("hello,aop");
        context.close();
    }
}


打印代码如下。


16:17:37.401 [main] INFO com.zzuhkp.blog.aop.CustomBeforeAdvisor - before,param is:[hello,aop]
16:17:39.229 [main] INFO com.zzuhkp.blog.aop.CustomAfterReturningAdvisor - after returning,param is:[hello,aop],result is:[param is : hello,aop]


成功为 IService 创建了代理。


总结

本篇主要介绍了 Spring AOP 三种使用方式,目前注解是主流的使用方式,同时 Spring 还支持使用 xml 配置自动创建代理,如果你对 Spring AOP 的 API 比较熟悉,还可以使用 ProxyFactory 手动为目标对象创建代理。除此之外,本篇还介绍了两个不常用创建代理的方式,分别是 DefaultAdvisorAutoProxyCreator 和 ProxyFactoryBean。相关源码阅读注释已上传到 github,感兴趣的小伙伴可自行下载阅读。


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
4天前
|
Java
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
这篇文章是Spring5框架的实战教程,深入讲解了AOP的基本概念、如何利用动态代理实现AOP,特别是通过JDK动态代理机制在不修改源代码的情况下为业务逻辑添加新功能,降低代码耦合度,并通过具体代码示例演示了JDK动态代理的实现过程。
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
|
1月前
|
Java Spring
在Spring Boot中使用AOP实现日志切面
在Spring Boot中使用AOP实现日志切面
|
4天前
|
XML Java 数据格式
Spring5入门到实战------11、使用XML方式实现AOP切面编程。具体代码+讲解
这篇文章是Spring5框架的AOP切面编程教程,通过XML配置方式,详细讲解了如何创建被增强类和增强类,如何在Spring配置文件中定义切入点和切面,以及如何将增强逻辑应用到具体方法上。文章通过具体的代码示例和测试结果,展示了使用XML配置实现AOP的过程,并强调了虽然注解开发更为便捷,但掌握XML配置也是非常重要的。
Spring5入门到实战------11、使用XML方式实现AOP切面编程。具体代码+讲解
|
6天前
|
安全 Java 开发者
Java 新手入门:Spring 两大利器IoC 和 AOP,小白也能轻松理解!
Java 新手入门:Spring 两大利器IoC 和 AOP,小白也能轻松理解!
14 1
|
6天前
|
Java Spring
Spring的AOP组件详解
该文章主要介绍了Spring AOP(面向切面编程)组件的实现原理,包括Spring AOP的基础概念、动态代理模式、AOP组件的实现以及Spring选择JDK动态代理或CGLIB动态代理的依据。
Spring的AOP组件详解
|
19天前
|
Java API Spring
Spring Boot 中的 AOP 处理
对 Spring Boot 中的切面 AOP 做了详细的讲解,主要介绍了 Spring Boot 中 AOP 的引入,常用注解的使用,参数的使用,以及常用 api 的介绍。AOP 在实际项目中很有用,对切面方法执行前后都可以根据具体的业务,做相应的预处理或者增强处理,同时也可以用作异常捕获处理,可以根据具体业务场景,合理去使用 AOP。
|
27天前
|
Java Spring 容器
Spring问题之Spring AOP是如何实现面向切面编程的
Spring问题之Spring AOP是如何实现面向切面编程的
|
23天前
|
缓存 安全 Java
Spring高手之路21——深入剖析Spring AOP代理对象的创建
本文详细介绍了Spring AOP代理对象的创建过程,分为三个核心步骤:判断是否增强、匹配增强器和创建代理对象。通过源码分析和时序图展示,深入剖析了Spring AOP的工作原理,帮助读者全面理解Spring AOP代理对象的生成机制及其实现细节。
17 0
Spring高手之路21——深入剖析Spring AOP代理对象的创建
|
4天前
|
XML Java 数据库
Spring5入门到实战------10、操作术语解释--Aspectj注解开发实例。AOP切面编程的实际应用
这篇文章是Spring5框架的实战教程,详细解释了AOP的关键术语,包括连接点、切入点、通知、切面,并展示了如何使用AspectJ注解来开发AOP实例,包括切入点表达式的编写、增强方法的配置、代理对象的创建和优先级设置,以及如何通过注解方式实现完全的AOP配置。
|
1月前
|
Java Spring
在Spring Boot中使用AOP实现日志切面
在Spring Boot中使用AOP实现日志切面