AOP源码解析之二-创建AOP代理前传,获取AOP信息

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 上篇文章对AOP的基本概念说清楚了,那么接下来的AOP还剩下两个大的步骤获取定义的AOP信息,生成代理对象扔到beanFactory中。

AOP源码解析之二-创建AOP代理前传,获取AOP信息


上篇文章对AOP的基本概念说清楚了,那么接下来的AOP还剩下两个大的步骤获取定义的AOP信息,生成代理对象扔到beanFactory中。


本篇文章重点对前半部分,如何获取到AOP信息的过程解读。

在Spring的核心方法Refresh方法中,aop是在

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);


开始切入的,该文章就开始深入这个方法进行解析。

@Nullable
  protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    // 检测是否被解析过
    if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
      // Make sure bean class is actually resolved at this point.
      // hasInstantiationAwareBeanPostProcessors()是来判断容器中是否有InstantiationAwareBeanPostProcessor的实现bean
      // AOP切面后置处理器AspectJAwareAdvisorAutoProxyCreator就实现了InstantiationAwareBeanPostProcessor接口
      if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        Class<?> targetType = determineTargetType(beanName, mbd);
        if (targetType != null) {
          // 执行实现了InstantiationAwareBeanPostProcessor接口的BeanPostProcessor中的前置处理方法postProcessBeforeInstantiation方法
          bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
          if (bean != null) {
            // 执行实现了InstantiationAwareBeanPostProcessor接口的BeanPostProcessor中的后置处理方法postProcessAfterInitialization方法
            bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
          }
        }
      }
      mbd.beforeInstantiationResolved = (bean != null);
    }
    return bean;
  }
TYPESCRIPT 复制 全屏


见名知意,resolveBeforeInstantiation(执行初始化前方法),这一步主要判断一下工厂中是否有 InstantiationAwareBeanPostProcessor 的实现bean。InstantiationAwareBeanPostProcessor 应该是AOP最核心的接口了。

我们看一下InstantiationAwareBeanPostProcessor 的继承结构。


我们详细的说下InstantiationAwareBeanPostProcessor 这个接口。

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
   Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;
   boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;
   PropertyValues postProcessPropertyValues(
         PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;
}


它和 BeanPostProcessor 的方法非常相似,而且它还继承了 BeanPostProcessor。

下面是 BeanPostProcessor 中的两个方法:

Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

发现没有,InstantiationAwareBeanPostProcessor 是 Instantiation,BeanPostProcessor 是 Initialization,它代表的是 bean 在实例化完成并且属性注入完成,在执行 init-method 的前后进行作用的。


而 InstantiationAwareBeanPostProcessor 的执行时机要前面一些,我们回到refresh方法的doCreateBean中看一下。


看到这读者想必对于aop的执行时机已经模模糊糊的心里有个大概了。

我们定义的环绕通知,创建代理一定是在postProcessBeforeInitialization完成的。

我们的重点就是看看postProcessBeforeInitialization的方法中的通知怎么获取,怎么创建代理对象的进行详细的解读。

本文先对前半部分解读。


我们继续看postProcessBeforeInitialization有哪些实现类。


我们重点看AbstractAutoProxyCreator的实现类。

@Override
  public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
      Object cacheKey = getCacheKey(bean.getClass(), beanName);
      // 1.判断当前bean是否需要被代理,如果需要则进行封装
      if (this.earlyProxyReferences.remove(cacheKey) != bean) {
        //1.判断当前bean是否需要被代理,如果需要则进行封装
        return wrapIfNecessary(bean, beanName, cacheKey);
      }
    }
    return bean;
  }


如果需要代理执行继wrapIfNecessary方法。

//这个方法将返回代理类
  protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    // 1.判断当前bean是否在targetSourcedBeans缓存中存在(已经处理过),如果存在,则直接返回当前bean
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
      return bean;
    }
    // 2.在advisedBeans缓存中存在,并且value为false,则代表无需处理
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
      return bean;
    }
    // 3.bean的类是aop基础设施类 || bean应该跳过,则标记为无需处理,并返回
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
      this.advisedBeans.put(cacheKey, Boolean.FALSE);
      return bean;
    }
    // Create proxy if we have advice.
    // 4.获取当前bean的Advices和Advisors
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    // 5.如果存在增强器则创建代理
    if (specificInterceptors != DO_NOT_PROXY) {
      this.advisedBeans.put(cacheKey, Boolean.TRUE);
      // 创建代理...创建代理...创建代理...
      // 5.1 创建代理对象:这边SingletonTargetSource的target属性存放的就是我们原来的bean实例(也就是被代理对象),
      // 用于最后增加逻辑执行完毕后,通过反射执行我们真正的方法时使用(method.invoke(bean, args))
      Object proxy = createProxy(
          bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
      // 5.2 创建完代理后,将cacheKey -> 代理类的class放到缓存
      this.proxyTypes.put(cacheKey, proxy.getClass());
      return proxy;
    }
    // 6.标记为无需处理
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
  }


4.1 我们先查看第一条主线,获取当前bean的Advices和Advisors

@Override
  @Nullable
  protected Object[] getAdvicesAndAdvisorsForBean(
      Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
    // 1.找到符合条件的Advisor
    List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
    if (advisors.isEmpty()) {
      // 2.如果没有符合条件的Advisor,则返回null
      return DO_NOT_PROXY;
    }
    return advisors.toArray();
  }


注:Advisors即是aop的环绕通知。


protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    // 1.查找所有的候选Advisor
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    // 2.从所有候选的Advisor中找出符合条件的
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    // 3.扩展方法,留个子类实现
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
      // 4.对符合条件的Advisor进行排序
      eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
  }


这一步所做的事很简单,就是查找所有候选的Advisor,但是调用链路特别的长,如果将这些彻底搞明白,还是需要耗费一番功夫的,读者可以选择深入程度。


1、寻找可用的Advisor

public List<Advisor> findAdvisorBeans() {
    // Determine list of advisor bean names, if not cached already.
    // 1.确认advisor的beanName列表,优先从缓存中拿
    String[] advisorNames = this.cachedAdvisorBeanNames;
    if (advisorNames == null) {
      // Do not initialize FactoryBeans here: We need to leave all regular beans
      // uninitialized to let the auto-proxy creator apply to them!
      //  1.1 如果缓存为空,则获取class类型为Advisor的所有bean名称
      advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
          this.beanFactory, Advisor.class, true, false);
      this.cachedAdvisorBeanNames = advisorNames;
    }
    if (advisorNames.length == 0) {
      return new ArrayList<>();
    }
    // 2.遍历处理advisorNames
    List<Advisor> advisors = new ArrayList<>();
    for (String name : advisorNames) {
      if (isEligibleBean(name)) {
        // 2.1 跳过当前正在创建的advisor
        if (this.beanFactory.isCurrentlyInCreation(name)) {
          if (logger.isTraceEnabled()) {
            logger.trace("Skipping currently created advisor '" + name + "'");
          }
        }
        else {
          try {
            // 2.2 通过beanName获取对应的bean对象,并添加到advisors
            advisors.add(this.beanFactory.getBean(name, Advisor.class));
          }
          catch (BeanCreationException ex) {
            Throwable rootCause = ex.getMostSpecificCause();
            if (rootCause instanceof BeanCurrentlyInCreationException) {
              BeanCreationException bce = (BeanCreationException) rootCause;
              String bceBeanName = bce.getBeanName();
              if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
                if (logger.isTraceEnabled()) {
                  logger.trace("Skipping advisor '" + name +
                      "' with dependency on currently created bean: " + ex.getMessage());
                }
                // Ignore: indicates a reference back to the bean we're trying to advise.
                // We want to find advisors other than the currently created bean itself.
                continue;
              }
            }
            throw ex;
          }
        }
      }
    }
    // 3.返回符合条件的advisor列表
    return advisors;
  }
/**
 * 找到符合条件的Advisor
 * @return
 */
@Override
protected List<Advisor> findCandidateAdvisors() {
   // Add all the Spring advisors found according to superclass rules.
   List<Advisor> advisors = super.findCandidateAdvisors();
   // Build Advisors for all AspectJ aspects in the bean factory.
   if (this.aspectJAdvisorsBuilder != null) {
      advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
   }
   return advisors;
}
public List<Advisor> buildAspectJAdvisors() {
   List<String> aspectNames = this.aspectBeanNames;
   // 1.如果aspectNames为空,则进行解析
   if (aspectNames == null) {
      synchronized (this) {
         aspectNames = this.aspectBeanNames;
         if (aspectNames == null) {
            List<Advisor> advisors = new ArrayList<>();
            aspectNames = new ArrayList<>();
            // 1.1 获取所有的beanName
            String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                  this.beanFactory, Object.class, true, false);
            // 1.2 循环遍历所有的beanName,找出对应的增强方法
            for (String beanName : beanNames) {
               // 1.3 不合法的beanName则跳过,默认返回true,子类可以覆盖实现,AnnotationAwareAspectJAutoProxyCreator
               // 实现了自己的逻辑,支持使用includePatterns进行筛选
               if (!isEligibleBean(beanName)) {
                  continue;
               }
               // We must be careful not to instantiate beans eagerly as in this case they
               // would be cached by the Spring container but would not have been weaved.
               // 获取beanName对应的bean的类型
               Class<?> beanType = this.beanFactory.getType(beanName);
               if (beanType == null) {
                  continue;
               }
               // 1.4 如果beanType存在Aspect注解则进行处理
               if (this.advisorFactory.isAspect(beanType)) {
                  // 将存在Aspect注解的beanName添加到aspectNames列表
                  aspectNames.add(beanName);
                  // 新建切面元数据
                  AspectMetadata amd = new AspectMetadata(beanType, beanName);
                  if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                     // 使用BeanFactory和beanName创建一个BeanFactoryAspectInstanceFactory,主要用来创建切面对象实例
                     MetadataAwareAspectInstanceFactory factory =
                           new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                     // 1.5 解析标记AspectJ注解中的增强方法*********************
                     List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
                     // 1.6 放到缓存中
                     if (this.beanFactory.isSingleton(beanName)) {
                        // 如果beanName是单例则直接将解析的增强方法放到缓存
                        this.advisorsCache.put(beanName, classAdvisors);
                     }
                     else {
                        // 如果不是单例,则将factory放到缓存,之后可以通过factory来解析增强方法
                        this.aspectFactoryCache.put(beanName, factory);
                     }
                     // 1.7 将解析的增强器添加到advisors
                     advisors.addAll(classAdvisors);
                  }
                  else {
                     // Per target or per this.
                     if (this.beanFactory.isSingleton(beanName)) {
                        // 名称为beanName的Bean是单例,但切面实例化模型不是单例,则抛异常
                        throw new IllegalArgumentException("Bean with name '" + beanName +
                              "' is a singleton, but aspect instantiation model is not singleton");
                     }
                     MetadataAwareAspectInstanceFactory factory =
                           new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
                     // 将factory放到缓存,之后可以通过factory来解析增强方法
                     this.aspectFactoryCache.put(beanName, factory);
                     // 解析标记AspectJ注解中的增强方法,并添加到advisors中
                     advisors.addAll(this.advisorFactory.getAdvisors(factory));
                  }
               }
            }
            // 1.9 将解析出来的切面beanName放到缓存aspectBeanNames
            this.aspectBeanNames = aspectNames;
            return advisors;
         }
      }
   }
   if (aspectNames.isEmpty()) {
      return Collections.emptyList();
   }
   List<Advisor> advisors = new ArrayList<>();
   for (String aspectName : aspectNames) {
      List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
      if (cachedAdvisors != null) {
         advisors.addAll(cachedAdvisors);
      }
      else {
         MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
         advisors.addAll(this.advisorFactory.getAdvisors(factory));
      }
   }
   // 1.10 最后返回解析出来的增强器
   return advisors;
}
@Override
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
   // 1.前面我们将beanClass和beanName封装成了aspectInstanceFactory的AspectMetadata属性,
   // 这边可以通过AspectMetadata属性重新获取到当前处理的切面类
   Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
   // 2.获取当前处理的切面类的名字
   String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
   // 3.校验切面类
   validate(aspectClass);
   // We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
   // so that it will only instantiate once.
   // 4.使用装饰器包装MetadataAwareAspectInstanceFactory,以便它只实例化一次。
   MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
         new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
   List<Advisor> advisors = new ArrayList<>();
   // 5.获取切面类中的方法(也就是我们用来进行逻辑增强的方法,被@Around、@After等注解修饰的方法,使用@Pointcut的方法不处理)
   for (Method method : getAdvisorMethods(aspectClass)) {
      // 6.处理method,获取增强器
      Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
      if (advisor != null) {
         // 7.如果增强器不为空,则添加到advisors
         advisors.add(advisor);
      }
   }
   // If it's a per target aspect, emit the dummy instantiating aspect.
   if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
      // 8.如果寻找的增强器不为空而且又配置了增强延迟初始化,那么需要在首位加入同步实例化增强器(用以保证增强使用之前的实例化)
      Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
      advisors.add(0, instantiationAdvisor);
   }
   // Find introduction fields.
   // 9.获取DeclareParents注解
   for (Field field : aspectClass.getDeclaredFields()) {
      Advisor advisor = getDeclareParentsAdvisor(field);
      if (advisor != null) {
         advisors.add(advisor);
      }
   }
   return advisors;
}
@Override
@Nullable
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
      int declarationOrderInAspect, String aspectName) {
   // 1.校验切面类
   validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
   // 2.AspectJ切点信息的获取(例如:表达式),就是指定注解的表达式信息的获取,
   // 如:@Around("execution(* com.joonwhee.open.aop.*.*(..))")
   AspectJExpressionPointcut expressionPointcut = getPointcut(
         candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
   // 3.如果expressionPointcut为null,则直接返回null
   if (expressionPointcut == null) {
      return null;
   }
   // 4.根据切点信息生成增强器
   return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
         this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}


获取到@Before, @Around, @After, @AfterReturning, @AfterThrowing, @Pointcut定义注解信息

@Nullable
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
   // 1.查找并返回给定方法的第一个AspectJ注解(@Before, @Around, @After, @AfterReturning, @AfterThrowing, @Pointcut)
   // 因为我们之前把@Pointcut注解的方法跳过了,所以这边必然不会获取到@Pointcut注解
   AspectJAnnotation<?> aspectJAnnotation =
         AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
   // 2.如果方法没有使用AspectJ的注解,则返回null
   if (aspectJAnnotation == null) {
      return null;
   }
   // 3.使用AspectJExpressionPointcut实例封装获取的信息
   AspectJExpressionPointcut ajexp =
         new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
   // 提取得到的注解中的表达式,
   // 例如:@Around("execution(* com.joonwhee.open.aop.*.*(..))"),得到:execution(* com.joonwhee.open.aop.*.*(..))
   ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
   if (this.beanFactory != null) {
      ajexp.setBeanFactory(this.beanFactory);
   }
   return ajexp;
}
@Nullable
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
   // 设置要查找的注解类
   for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
      // 查找方法上是否存在当前遍历的注解,如果有则返回
      AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
      if (foundAnnotation != null) {
         return foundAnnotation;
      }
   }
   return null;
}


2、获取切点以后就需要生成增强器了。

new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
        this, aspectInstanceFactory, declarationOrderInAspect, aspectName)
/**
 * 根据切点信息生成增强器
 * @param declaredPointcut
 * @param aspectJAdviceMethod
 * @param aspectJAdvisorFactory
 * @param aspectInstanceFactory
 * @param declarationOrder
 * @param aspectName
 */
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
      Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
      MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
   // 1.简单的将信息封装在类的实例中
   this.declaredPointcut = declaredPointcut;
   this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
   this.methodName = aspectJAdviceMethod.getName();
   this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
   // aspectJAdviceMethod保存的是我们用来进行逻辑增强的方法(@Around、@After等修饰的方法)
   this.aspectJAdviceMethod = aspectJAdviceMethod;
   this.aspectJAdvisorFactory = aspectJAdvisorFactory;
   this.aspectInstanceFactory = aspectInstanceFactory;
   this.declarationOrder = declarationOrder;
   this.aspectName = aspectName;
   // 2.是否需要延迟实例化
   if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
      // Static part of the pointcut is a lazy type.
      Pointcut preInstantiationPointcut = Pointcuts.union(
            aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
      // Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
      // If it's not a dynamic pointcut, it may be optimized out
      // by the Spring AOP infrastructure after the first evaluation.
      this.pointcut = new PerTargetInstantiationModelPointcut(
            this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
      this.lazy = true;
   }
   else {
      // A singleton aspect.
      this.pointcut = this.declaredPointcut;
      this.lazy = false;
      // 3.实例化增强器:根据注解中的信息初始化对应的增强器
      this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
   }
}


经过以上长长的源码分析过程,就将aop的第一个大过程,获取到我们定义的@Before、@After的方法以后,进行增强,下一步就要拿到这些获取的信息去创建代理对象了。


相关文章
|
1天前
|
机器学习/深度学习 自然语言处理 算法
生成式 AI 大语言模型(LLMs)核心算法及源码解析:预训练篇
生成式 AI 大语言模型(LLMs)核心算法及源码解析:预训练篇
|
2月前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是"将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。创建型模式分为5种:单例模式、工厂方法模式抽象工厂式、原型模式、建造者模式。
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
2月前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
|
2月前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。 结构型模式分为以下 7 种: • 代理模式 • 适配器模式 • 装饰者模式 • 桥接模式 • 外观模式 • 组合模式 • 享元模式
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
1月前
|
自然语言处理 数据处理 索引
mindspeed-llm源码解析(一)preprocess_data
mindspeed-llm是昇腾模型套件代码仓,原来叫"modelLink"。这篇文章带大家阅读一下数据处理脚本preprocess_data.py(基于1.0.0分支),数据处理是模型训练的第一步,经常会用到。
60 0
|
2月前
|
PyTorch Shell API
Ascend Extension for PyTorch的源码解析
本文介绍了Ascend对PyTorch代码的适配过程,包括源码下载、编译步骤及常见问题,详细解析了torch-npu编译后的文件结构和三种实现昇腾NPU算子调用的方式:通过torch的register方式、定义算子方式和API重定向映射方式。这对于开发者理解和使用Ascend平台上的PyTorch具有重要指导意义。
|
2月前
|
安全 搜索推荐 数据挖掘
陪玩系统源码开发流程解析,成品陪玩系统源码的优点
我们自主开发的多客陪玩系统源码,整合了市面上主流陪玩APP功能,支持二次开发。该系统适用于线上游戏陪玩、语音视频聊天、心理咨询等场景,提供用户注册管理、陪玩者资料库、预约匹配、实时通讯、支付结算、安全隐私保护、客户服务及数据分析等功能,打造综合性社交平台。随着互联网技术发展,陪玩系统正成为游戏爱好者的新宠,改变游戏体验并带来新的商业模式。
|
3月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
140 2
|
4月前
|
缓存 Java 程序员
Map - LinkedHashSet&Map源码解析
Map - LinkedHashSet&Map源码解析
101 1
|
4月前
|
算法 Java 容器
Map - HashSet & HashMap 源码解析
Map - HashSet & HashMap 源码解析
88 0

推荐镜像

更多