【小家Spring】Spring AOP之Advisor、PointcutAdvisor、IntroductionAdvisor、IntroductionInterceptor(引介增强)(下)

简介: 【小家Spring】Spring AOP之Advisor、PointcutAdvisor、IntroductionAdvisor、IntroductionInterceptor(引介增强)(下)

我们发现,我们没有更改过Person类的任何代码,它竟然就有了doOther()方法的功能,这就是引介增强的强大功能。此处使用的Advisor为DefaultIntroductionAdvisor。它也是我们最常用的Advisor:


// 它是一个Advisor,同时也是一个IntroductionInfo 
public interface IntroductionAdvisor extends Advisor, IntroductionInfo {
  // 它只有ClassFilter,因为它只能作用在类层面上
  ClassFilter getClassFilter();
  // 判断这些接口,是否真的能够增强。  DynamicIntroductionAdvice#implementsInterface()方法
  void validateInterfaces() throws IllegalArgumentException;
}
// 它直接事IntroductionAdvisor的实现类。同时也是一个ClassFilter
public class DefaultIntroductionAdvisor implements IntroductionAdvisor, ClassFilter, Ordered, Serializable {
  private final Advice advice;
  private final Set<Class<?>> interfaces = new LinkedHashSet<>();
  private int order = Ordered.LOWEST_PRECEDENCE;
  // 构造函数们
  public DefaultIntroductionAdvisor(Advice advice) {
    this(advice, (advice instanceof IntroductionInfo ? (IntroductionInfo) advice : null));
  }
  // 如果IntroductionInfo 不等于null,就会把接口都add进去/
  // IntroductionInfo 的实现类有常用的:DelegatingIntroductionInterceptor和DelegatePerTargetObjectIntroductionInterceptor
  public DefaultIntroductionAdvisor(Advice advice, @Nullable IntroductionInfo introductionInfo) {
    Assert.notNull(advice, "Advice must not be null");
    this.advice = advice;
    if (introductionInfo != null) {
      Class<?>[] introducedInterfaces = introductionInfo.getInterfaces();
      if (introducedInterfaces.length == 0) {
        throw new IllegalArgumentException("IntroductionAdviceSupport implements no interfaces");
      }
      for (Class<?> ifc : introducedInterfaces) {
        addInterface(ifc);
      }
    }
  }
  //当然你也可以不使用IntroductionInfo,而自己手动指定了这个接口
  public DefaultIntroductionAdvisor(DynamicIntroductionAdvice advice, Class<?> intf) {
    Assert.notNull(advice, "Advice must not be null");
    this.advice = advice;
    addInterface(intf);
  }
  ...
  @Override
  public void validateInterfaces() throws IllegalArgumentException {
    for (Class<?> ifc : this.interfaces) {
      if (this.advice instanceof DynamicIntroductionAdvice &&
          !((DynamicIntroductionAdvice) this.advice).implementsInterface(ifc)) {
       throw new IllegalArgumentException("DynamicIntroductionAdvice [" + this.advice + "] " +
           "does not implement interface [" + ifc.getName() + "] specified for introduction");
      }
    }
  }
  ...
}

DelegatingIntroductionInterceptor和DelegatePerTargetObjectIntroductionInterceptor


这两个类是 Spring AOP 中为 IntroductionInterceptor 介面所提供的实作类别,我们可以直接继承他俩,然后扩展我们自己的行为状态。

public class DelegatingIntroductionInterceptor extends IntroductionInfoSupport
    implements IntroductionInterceptor {
  // 需要被代理的那个对象。因为这个类需要子类继承使用,所以一般都是thid
  @Nullable
  private Object delegate;
  /**
   * Construct a new DelegatingIntroductionInterceptor.
   * The delegate will be the subclass, which must implement
   * additional interfaces.
   * 访问权限事protected,显然就是说子类必须去继承这个类,然后提供空构造函数。代理类就是this
   */
  protected DelegatingIntroductionInterceptor() {
    init(this);
  }
  // 当然,你也可以手动指定delegate
  public DelegatingIntroductionInterceptor(Object delegate) {
    init(delegate);
  }
  private void init(Object delegate) {
    Assert.notNull(delegate, "Delegate must not be null");
    this.delegate = delegate;
    implementInterfacesOnObject(delegate);
    // 移除调这些内部标记的接口们
    // We don't want to expose the control interface
    suppressInterface(IntroductionInterceptor.class);
    suppressInterface(DynamicIntroductionAdvice.class);
  }
  // 如果你要自定义一些行为:比如环绕通知之类的,子类需要复写此方法(否则没有必要了)
  @Override
  @Nullable
  public Object invoke(MethodInvocation mi) throws Throwable {
    // 判断是否是引介增强
    if (isMethodOnIntroducedInterface(mi)) {
      Object retVal = AopUtils.invokeJoinpointUsingReflection(this.delegate, mi.getMethod(), mi.getArguments());
      // 如果返回值就是delegate 本身,那就把本身返回出去
      if (retVal == this.delegate && mi instanceof ProxyMethodInvocation) {
        Object proxy = ((ProxyMethodInvocation) mi).getProxy();
        if (mi.getMethod().getReturnType().isInstance(proxy)) {
          retVal = proxy;
        }
      }
      return retVal;
    }
    return doProceed(mi);
  }
  ...
}


因此,上面的例子Demo,我用DelegatingIntroductionInterceptor改造一下(只需要改造SomeInteIntroductionInterceptor即可):

// 因为我们继承自DelegatingIntroductionInterceptor,所以若我们不做环绕通知个性化,只需要实现接口的方法即可
public class SomeInteIntroductionInterceptor extends DelegatingIntroductionInterceptor implements IOtherInte {
    @Override
    public void doOther() {
        System.out.println("给人贴标签 doOther...");
    }
}


继承此类,确实少了不少事呢。


DelegatePerTargetObjectIntroductionInterceptor


与DelegatingIntroductionInterceptor不同,DelegatePerTargetObjectIntroductionInterceptor会在内部持有一个目标对象与相应Introduction逻辑实现类之间的映射关系。


当每个目标对象上的新定义的接口方法被调用的时候,它会拦截这些调用。然后以目标对象实例作为键,到它持有的那个映射关系中取得对应当前目标对象实例的Introduction实现类实例。 使用起来和DelegatingIntroductionInterceptor没有太大区别,主要在构造函数上:

1: 可以删除掉SomeInteIntroductionInterceptor类了
2:单独实现引介接口
public class OtherImpl implements IOtherInte {
    @Override
    public void doOther() {
        System.out.println("我是OtherImpl");
    }
}
main方法里修改如下:这样就ok了
Advice advice = new DelegatePerTargetObjectIntroductionInterceptor(OtherImpl.class, IOtherInte.class);


备注:若你需要复写invoke方法的逻辑,请扩展它即可~~~(它的优点是:每次执行目标对象的时候,都可议缓存起来,提高一点效率吧)


总结


Advisor是Spring AOP中非常重要的一个概念,最终代理对象进行执行什么的,都是适配到此处,因此需要重点掌握。


其中,引介增强平时使用得较少,但是在特殊的场景下,它能够解决某一类问题,还是非常不错的~

相关文章
|
8天前
|
XML Java 开发者
Spring Boot中的AOP实现
Spring AOP(面向切面编程)允许开发者在不修改原有业务逻辑的情况下增强功能,基于代理模式拦截和增强方法调用。Spring Boot通过集成Spring AOP和AspectJ简化了AOP的使用,只需添加依赖并定义切面类。关键概念包括切面、通知和切点。切面类使用`@Aspect`和`@Component`注解标注,通知定义切面行为,切点定义应用位置。Spring Boot自动检测并创建代理对象,支持JDK动态代理和CGLIB代理。通过源码分析可深入了解其实现细节,优化应用功能。
|
16天前
|
存储 安全 Java
Spring Boot 3 集成Spring AOP实现系统日志记录
本文介绍了如何在Spring Boot 3中集成Spring AOP实现系统日志记录功能。通过定义`SysLog`注解和配置相应的AOP切面,可以在方法执行前后自动记录日志信息,包括操作的开始时间、结束时间、请求参数、返回结果、异常信息等,并将这些信息保存到数据库中。此外,还使用了`ThreadLocal`变量来存储每个线程独立的日志数据,确保线程安全。文中还展示了项目实战中的部分代码片段,以及基于Spring Boot 3 + Vue 3构建的快速开发框架的简介与内置功能列表。此框架结合了当前主流技术栈,提供了用户管理、权限控制、接口文档自动生成等多项实用特性。
68 8
|
2月前
|
XML Java 数据安全/隐私保护
Spring Aop该如何使用
本文介绍了AOP(面向切面编程)的基本概念和术语,并通过具体业务场景演示了如何在Spring框架中使用Spring AOP。文章详细解释了切面、连接点、通知、切点等关键术语,并提供了完整的示例代码,帮助读者轻松理解和应用Spring AOP。
Spring Aop该如何使用
|
2月前
|
监控 安全 Java
什么是AOP?如何与Spring Boot一起使用?
什么是AOP?如何与Spring Boot一起使用?
99 5
|
2月前
|
Java 开发者 Spring
深入解析:Spring AOP的底层实现机制
在现代软件开发中,Spring框架的AOP(面向切面编程)功能因其能够有效分离横切关注点(如日志记录、事务管理等)而备受青睐。本文将深入探讨Spring AOP的底层原理,揭示其如何通过动态代理技术实现方法的增强。
92 8
|
2月前
|
Java 开发者 Spring
Spring AOP 底层原理技术分享
Spring AOP(面向切面编程)是Spring框架中一个强大的功能,它允许开发者在不修改业务逻辑代码的情况下,增加额外的功能,如日志记录、事务管理等。本文将深入探讨Spring AOP的底层原理,包括其核心概念、实现方式以及如何与Spring框架协同工作。
|
2月前
|
XML 监控 安全
深入调查研究Spring AOP
【11月更文挑战第15天】
54 5
|
2月前
|
Java 开发者 Spring
Spring AOP深度解析:探秘动态代理与增强逻辑
Spring框架中的AOP(Aspect-Oriented Programming,面向切面编程)功能为开发者提供了一种强大的工具,用以将横切关注点(如日志、事务管理等)与业务逻辑分离。本文将深入探讨Spring AOP的底层原理,包括动态代理机制和增强逻辑的实现。
60 4
|
2月前
|
Java Spring
[Spring]aop的配置与使用
本文介绍了AOP(面向切面编程)的基本概念和核心思想。AOP是Spring框架的核心功能之一,通过动态代理在不修改原代码的情况下注入新功能。文章详细解释了连接点、切入点、通知、切面等关键概念,并列举了前置通知、后置通知、最终通知、异常通知和环绕通知五种通知类型。
51 1
|
2月前
|
安全 Java 测试技术
Java开发必读,谈谈对Spring IOC与AOP的理解
Spring的IOC和AOP机制通过依赖注入和横切关注点的分离,大大提高了代码的模块化和可维护性。IOC使得对象的创建和管理变得灵活可控,降低了对象之间的耦合度;AOP则通过动态代理机制实现了横切关注点的集中管理,减少了重复代码。理解和掌握这两个核心概念,是高效使用Spring框架的关键。希望本文对你深入理解Spring的IOC和AOP有所帮助。
55 0