如何实现一个简易版的 Spring - 如何实现 AOP(终结篇)

前言

上篇 实现了 判断一个类的方式是符合配置的 pointcut 表达式、根据一个 Bean 的名称和方法名,获取 Method 对象、实现了 BeforeAdvice、AfterReturningAdvice 以及 AfterThrowingAdvice并按照指定次序调用 等功能,这篇再来看看剩下的 代理对象如何生成根据 XML 配置文件生成 BeanDefintion以及如何将生成的代理对象放入到容器中 等功能,话不多说,下面进入主题。

代理对象生成

代理对象的生成策略和 Spring 框架一致,当被代理类实现了接口时采用 JDK 动态代理的方式生成代理对象,被代理对象未实现接口时使用 CGLIB 来生成代理对象,为了简单起见这里不支持手动指定生成代理对象的策略,JDK 动态代理的实现这里不在介绍,感兴趣可以自己实现一下,这里主要讨论 CGLIB 的生成方式。

在这里插入图片描述

基于面向接口编程的思想,这里的生成代理对象需要定义一个统一的接口,不管是 CGLIB 生成方式还是JDK 动态代理生成方式都要实现该接口。生成代理对象是根据一些配置去生成的,同样,这里生成代理的配置也可以抽取一个统一的接口,在实现类中定义拦截器(也就是 Advice)以及实现的接口等,CGLIB 的基本使用可以到官网自行查找。代理对象生成的整体的类图如下:

在这里插入图片描述

其中代理创建的工厂接口 AopProxyFactory 如下,提供了不指定 ClassLoader(使用默认的 ClassLoader)和指定 ClassLoader 两种方式创建代理对象,源码如下:

/**
 * @author mghio
 * @since 2021-06-13
 */
public interface AopProxyFactory {

  Object getProxy();

  Object getProxy(ClassLoader classLoader);

}

使用 CGLIB 创建代理的工厂接口实现类如下所示:

/**
 * @author mghio
 * @since 2021-06-13
 */
public class CglibProxyFactory implements AopProxyFactory {

  /*
   * Constants for CGLIB callback array indices
   */
  private static final int AOP_PROXY = 0;

  protected final Advised advised;

  public CglibProxyFactory(Advised config) {
    Assert.notNull(config, "AdvisedSupport must not be null");
    if (config.getAdvices().size() == 0) {
      throw new AopConfigException("No advisors and no TargetSource specified");
    }

    this.advised = config;
  }

  @Override
  public Object getProxy() {
    return getProxy(null);
  }

  @Override
  public Object getProxy(ClassLoader classLoader) {
    if (logger.isDebugEnabled()) {
      logger.debug("Creating CGLIB proxy: target class is " + this.advised.getTargetClass());
    }

    try {
      Class<?> rootClass = this.advised.getTargetClass();

      // Configure CGLIB Enhancer...
      Enhancer enhancer = new Enhancer();
      if (classLoader != null) {
        enhancer.setClassLoader(classLoader);
      }
      enhancer.setSuperclass(rootClass);
      enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);  // BySpringCGLIB
      enhancer.setInterceptDuringConstruction(false);

      Callback[] callbacks = getCallbacks(rootClass);
      Class<?>[] types = new Class<?>[callbacks.length];
      for (int i = 0; i < types.length; i++) {
        types[i] = callbacks[i].getClass();
      }
      enhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised));
      enhancer.setCallbackTypes(types);
      enhancer.setCallbacks(callbacks);

      // Generate the proxy class and create a proxy instance.
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值