面试 — 进行时 — Spring AOP

好记忆不如烂笔头,能记下点东西,就记下点,有时间拿出来看看,也会发觉不一样的感受.

说说 spring aop 的那些事。

Spring AOP 的前世今生

  • 起源与发展 :AOP(Aspect-Oriented Programming,面向切面编程)作为一种编程思想,旨在解决传统面向对象编程中存在的代码重复、关注点分散等问题。Spring AOP 是 Spring 框架对 AOP 思想的实现,它借鉴了 AOP Alliance 的相关规范,并不断发展和完善。

  • 与 AspectJ 的关系 :早期 Spring AOP 和 AspectJ 是相互竞争的 AOP 框架,但后来 Spring 决定整合 AspectJ,从 Spring 2.0 开始对 AspectJ 提供支持,并在后续版本中不断加深融合。不过,Spring AOP 和 AspectJ 在实现原理和使用场景上有所不同,Spring AOP 主要基于动态代理实现运行时增强,而 AspectJ 是基于字节码操作的编译时增强。

Spring AOP 的核心设计思想

  • 代码复用 :将通用的功能(如日志记录、事务管理等)抽取出来,形成可复用的切面模块,避免在多个业务模块中重复编写相同的代码,提高代码的可维护性和可扩展性。

  • 关注点分离 :将业务逻辑和通用功能分离,让开发者能够更专注于业务逻辑的实现,而通用功能则由切面来处理,从而使代码更加清晰、简洁,降低模块间的耦合度。

  • 动态织入 :在运行时通过动态代理技术将切面逻辑织入到目标对象的方法中,无需修改目标对象的源代码,实现了对目标对象的无侵入式增强,增强了系统的灵活性和可扩展性。

  • 基于接口与注解的编程模式 :提供了丰富的注解(如 @Aspect、@Before、@After、@Around 等),方便开发者快速定义切面和切点,降低了 AOP 编程的门槛,同时也支持基于接口的编程模式,与 Spring 容器紧密结合,方便对切面进行管理。

  • 与 Spring 容器的集成 :依赖于 Spring 的 IOC 容器,能够方便地获取和管理切面 Bean,同时也能够利用 Spring 容器的其他功能(如依赖注入等)来增强切面的灵活性和可配置性。

Spring AOP 的核心实现源码

  • AOP 代理的创建 :Spring AOP 通过 AopProxyFactory 来创建 AOP 代理对象,它会根据目标对象是否实现了接口以及相关配置来决定使用 JDK 动态代理还是 CGLIB 代理。其核心实现代码如下:扫码添加如下号码,了解更多信息。

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
            Class<?> targetClass = config.getTargetClass();
            if (targetClass == null) {
                throw new AopConfigException("TargetSource cannot determine target class: " +
                        "Either an interface or a target is required for proxy creation.");
            }
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                return new JdkDynamicAopProxy(config);
            }
            return new ObjenesisCglibAopProxy(config);
        }
        else {
            return new JdkDynamicAopProxy(config);
        }
    }

    private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
        Class<?>[] ifcs = config.getProxiedInterfaces();
        return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
    }
}
  • 方法拦截器链的执行 :在 Spring AOP 中,方法拦截器链的执行是通过 ReflectiveMethodInvocation 类来实现的,其核心代码如下:

public class ReflectiveMethodInvocation extends AbstractMethodInvocation {
    // 方法拦截器链
    private final List<Object> interceptorsAndDynamicMethodMatchers;
    private final Class<?> targetClass;
    private final Object[] arguments;
    private final Method method;
    private final Object target;
    // 其他代码...

    public Object proceed() throws Throwable {
        Object returnType = null;
        for (int i = 0; i < interceptorsAndDynamicMethodMatchers.size() - 1; i++) {
            Object interceptorOrInterceptionAdvice = interceptorsAndDynamicMethodMatchers.get(i);
            if (interceptorOrInterceptionAdvice instanceof MethodInterceptor) {
                returnType = ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
                if (returnType != null) {
                    return returnType;
                }
            }
        }
        return invokeJoinpoint();
    }

    private Object invokeJoinpoint() throws Throwable {
        return AopUtils.invokeJoinpointUsingReflection(target, method, arguments);
    }
}
  • 环绕通知的实现 :环绕通知是 Spring AOP 中一种强大的通知类型,它允许在目标方法执行前后都执行自定义逻辑,并且可以控制目标方法是否执行以及返回值等。环绕通知的核心实现代码如下:

public class AroundAdviceInterceptor implements MethodInterceptor {
    private final MethodInterceptor interceptor;

    public AroundAdviceInterceptor(MethodInterceptor interceptor) {
        this.interceptor = interceptor;
    }

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        return this.interceptor.invoke(invocation);
    }
}

Spring AOP 的使用场景

  • 日志记录 :在方法执行前后记录日志信息,方便对系统的运行情况进行监控和分析。

  • 权限验证 :在业务方法执行前进行权限验证,确保只有具有相应权限的用户才能访问特定的方法或功能。

  • 性能监控 :通过环绕通知测量方法的执行时间,对系统的性能进行监控和优化。

  • 事务管理 :对数据访问层的方法进行事务管理,确保数据的一致性和完整性。

  • 缓存管理 :在方法执行前检查缓存中是否存在结果,如果存在则直接返回缓存结果,否则执行方法并将结果存入缓存。

  • 异常处理 :在方法执行出现异常时进行统一的异常处理,如记录异常信息、发送警报邮件等。

Spring AOP 的替代方案

  • AspectJ :AspectJ 是一个功能强大的 AOP 框架,它基于字节码操作实现编译时增强,能够对类的字段、构造方法等进行增强,且性能较好。Spring AOP 已经集成了 AspectJ,但在使用时需要注意二者的区别和适用场景。

  • 字节码增强工具 :如 ASM、Javassist 等,它们可以直接操作字节码来实现对类的增强,具有较高的灵活性和性能,但使用相对复杂,需要对字节码有一定的了解。

  • 其他 AOP 框架 :如 Guice AOP 等,它们也提供了类似的功能,可根据具体需求选择合适的框架。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值