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日志并进行多维度分析。
目录
相关文章
|
3月前
|
Java
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
这篇文章是Spring5框架的实战教程,深入讲解了AOP的基本概念、如何利用动态代理实现AOP,特别是通过JDK动态代理机制在不修改源代码的情况下为业务逻辑添加新功能,降低代码耦合度,并通过具体代码示例演示了JDK动态代理的实现过程。
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
|
15天前
|
XML Java 数据安全/隐私保护
Spring Aop该如何使用
本文介绍了AOP(面向切面编程)的基本概念和术语,并通过具体业务场景演示了如何在Spring框架中使用Spring AOP。文章详细解释了切面、连接点、通知、切点等关键术语,并提供了完整的示例代码,帮助读者轻松理解和应用Spring AOP。
Spring Aop该如何使用
|
1月前
|
存储 缓存 Java
Spring高手之路23——AOP触发机制与代理逻辑的执行
本篇文章深入解析了Spring AOP代理的触发机制和执行流程,从源码角度详细讲解了Bean如何被AOP代理,包括代理对象的创建、配置与执行逻辑,帮助读者全面掌握Spring AOP的核心技术。
40 3
Spring高手之路23——AOP触发机制与代理逻辑的执行
|
21天前
|
Java Spring
[Spring]aop的配置与使用
本文介绍了AOP(面向切面编程)的基本概念和核心思想。AOP是Spring框架的核心功能之一,通过动态代理在不修改原代码的情况下注入新功能。文章详细解释了连接点、切入点、通知、切面等关键概念,并列举了前置通知、后置通知、最终通知、异常通知和环绕通知五种通知类型。
30 1
|
17天前
|
安全 Java 测试技术
Java开发必读,谈谈对Spring IOC与AOP的理解
Spring的IOC和AOP机制通过依赖注入和横切关注点的分离,大大提高了代码的模块化和可维护性。IOC使得对象的创建和管理变得灵活可控,降低了对象之间的耦合度;AOP则通过动态代理机制实现了横切关注点的集中管理,减少了重复代码。理解和掌握这两个核心概念,是高效使用Spring框架的关键。希望本文对你深入理解Spring的IOC和AOP有所帮助。
31 0
|
2月前
|
设计模式 Java 测试技术
spring复习04,静态代理动态代理,AOP
这篇文章讲解了Java代理模式的相关知识,包括静态代理和动态代理(JDK动态代理和CGLIB),以及AOP(面向切面编程)的概念和在Spring框架中的应用。文章还提供了详细的示例代码,演示了如何使用Spring AOP进行方法增强和代理对象的创建。
spring复习04,静态代理动态代理,AOP
|
1月前
|
Java 编译器 Spring
Spring AOP 和 AspectJ 的区别
Spring AOP和AspectJ AOP都是面向切面编程(AOP)的实现,但它们在实现方式、灵活性、依赖性、性能和使用场景等方面存在显著区别。‌
79 2
|
1月前
|
Java Spring 容器
Spring IOC、AOP与事务管理底层原理及源码解析
【10月更文挑战第1天】Spring框架以其强大的控制反转(IOC)和面向切面编程(AOP)功能,成为Java企业级开发中的首选框架。本文将深入探讨Spring IOC和AOP的底层原理,并通过源码解析来揭示其实现机制。同时,我们还将探讨Spring事务管理的核心原理,并给出相应的源码示例。
130 9
|
1月前
|
XML Java 数据格式
Spring的IOC和AOP
Spring的IOC和AOP
48 0
|
2月前
|
Java 数据库连接 数据库
Spring基础3——AOP,事务管理
AOP简介、入门案例、工作流程、切入点表达式、环绕通知、通知获取参数或返回值或异常、事务管理
Spring基础3——AOP,事务管理
下一篇
无影云桌面