Spring5源码解析二

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: //上面的是扫描普通的bean //处理@Import的3种情况(正常类;ImportSelector类;ImportBeanDefinitionRegistrar类) private void pr

//上面的是扫描普通的bean

//处理@Import的3种情况(正常类;ImportSelector类;ImportBeanDefinitionRegistrar类)
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,

        Collection<SourceClass> importCandidates, boolean checkForCircularImports) {
if (importCandidates.isEmpty()) {
    return;
}

if (checkForCircularImports && isChainedImportOnStack(configClass)) {
    this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
    this.importStack.push(configClass);
    try {
        for (SourceClass candidate : importCandidates) {
            if (candidate.isAssignable(ImportSelector.class)) {
                // Candidate class is an ImportSelector -> delegate to it to determine imports
                Class<?> candidateClass = candidate.loadClass();
                //反射实现一个对象
                ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
                ParserStrategyUtils.invokeAwareMethods(
                        selector, this.environment, this.resourceLoader, this.registry);
                if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
                    this.deferredImportSelectors.add(
                            new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
                }
                else {
                    //回调
                    String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                    Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
                    //递归,这里第二次调用processImports
                    //如果是一个普通类,会斤else
                    processImports(configClass, currentSourceClass, importSourceClasses, false);
                }
            }
            else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
                // Candidate class is an ImportBeanDefinitionRegistrar ->
                // delegate to it to register additional bean definitions
                Class<?> candidateClass = candidate.loadClass();
                ImportBeanDefinitionRegistrar registrar =
                        BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
                ParserStrategyUtils.invokeAwareMethods(
                        registrar, this.environment, this.resourceLoader, this.registry);
                //添加到一个list当中和importselector不同
                configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
            }
            else {
                // Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
                // process it as an @Configuration class
                // 否则,加入到importStack后调用processConfigurationClass 进行处理
                //processConfigurationClass里面主要就是把类放到configurationClasses
                //configurationClasses是一个集合,会在后面拿出来解析成bd继而注册
                //可以看到普通类在扫描出来的时候就被注册了
                //如果是importSelector,会先放到configurationClasses后面进行出来注册
                this.importStack.registerImport(
                        currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
                processConfigurationClass(candidate.asConfigClass(configClass));
            }
        }
    }
    catch (BeanDefinitionStoreException ex) {
        throw ex;
    }
    catch (Throwable ex) {
        throw new BeanDefinitionStoreException(
                "Failed to process imports candidates for configuration class [" +
                configClass.getMetadata().getClassName() + "]", ex);
    }
    finally {
        this.importStack.pop();
    }
}

}


>processImports,处理import的类,主要是处理3种。
>1. 普通的bean
>2. 实现了 importSelector的bean(可以注册多个类的String数组字符串)
>3. 实现了ImportBeanDefinitionRegistrar

>1. import普通的bean,会先加入到importStack后调用processConfigurationClass 进行处理,放入到configurationClasses后面进行出来注册。
>2. import的是importSelector,会先实例化这个ImportSelector 类,然后执行该selector的selectImports方法,获取要注入到spring的bean工厂的类数组字符串,然后 对该String[]数组,进行再一次调用processImports方法处理,最终都是会进入到import普通bean的步骤,即:会先加入到importStack后调用processConfigurationClass 进行处理,放入到configurationClasses后面进行出来注册。
>3. import的是ImportBeanDefinitionRegistrar,会先实例化这个ImportBeanDefinitionRegistrar类,然后将它添加到一个list当中和importselector不同。

对于import的bean处理,是在 ConfigurationClassPostProcessor # processConfigBeanDefinitions()方法处理,即下面代码:

/**

  • 这里值得注意的是扫描出来的bean当中可能包含了特殊类

    • 比如ImportBeanDefinitionRegistrar那么也在这个方法里面处理
    • 但是并不是包含在configClasses当中
    • configClasses当中主要包含的是importSelector
    • 因为ImportBeanDefinitionRegistrar在扫描出来的时候已经被添加到一个list当中去了

    */

//bd 到 map 除却普通
this.reader.loadBeanDefinitions(configClasses);

//ConfigurationClassBeanDefinitionReader
public void loadBeanDefinitions(Set configurationModel) {

TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
for (ConfigurationClass configClass : configurationModel) {
    loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}

}

private void loadBeanDefinitionsForConfigurationClass(

    ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {

if (trackedConditionEvaluator.shouldSkip(configClass)) {
    String beanName = configClass.getBeanName();
    if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
        this.registry.removeBeanDefinition(beanName);
    }
    this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
    return;
}

//如果一个类是被import的,会被spring标准
//早这里完成注册
if (configClass.isImported()) {
    registerBeanDefinitionForImportedConfigurationClass(configClass);
}
//@Bean
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
    loadBeanDefinitionsForBeanMethod(beanMethod);
}

 //xml
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());

//注册Registrar
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());

}

//将import和importSelector注入的bean,注册到bean工厂中
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {

AnnotationMetadata metadata = configClass.getMetadata();
AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);

ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
configBeanDef.setScope(scopeMetadata.getScopeName());
String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);

BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
configClass.setBeanName(configBeanName);

if (logger.isDebugEnabled()) {
    logger.debug("Registered bean definition for imported class '" + configBeanName + "'");
}

}

//将ImportBeanDefinitionRegistrar注入的bean,注册到bean工厂中
private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {

registrars.forEach((registrar, metadata) ->
        registrar.registerBeanDefinitions(metadata, this.registry));

}

> 总结:spring扫描类分了4种情况
> 1. 普通类,扫描到即刻注册到beanDefinitionMap中。
> 2. import(普通类),扫描到先存放到configurationClasses一个map集合。
> 3. import(importSelector),扫描到遍历循环一个一个的放到configurationClasses一个map集合。
> 4. import(importBeanDefinitionRegistrar),扫描到之后存放到importBeanDefinitionRegistrars一个map集合中。
> 备注:对于import的类,spring是在扫描之后,调用了loadBeanDefinitions方法将扫描到import的类注册到beanDefinitionMap中。

> full和lite的主要作用:
> 1. 当一个bean加了@Configuration注解,即是full全注解类。
> 2. 当一个bean加了@Component、@ComponentScan、@Import、@ImportResource等注解,即是lite
>备注:full全注解类,spring会为该类生成一个cglib代理类。

> 对于加了@Configuration注解的类,spring会对该类使用cglib产生一个代理类。
> 为什么需要使用cglib代理?
> > AppConfig类,使用@Bean注入了两个bean,在configDao2()方法中调用了configDao1()方法,这里就是为了防止configDao1对象被创建两次的问题。
> 
> 备注:cglib是基于继承的。
> 是在invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);方法执行的。

private static void invokeBeanFactoryPostProcessors(

        Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
//因为只有一条数据ConfigurationClassPostProcessor
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
    postProcessor.postProcessBeanFactory(beanFactory);
}

}

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {

int factoryId = System.identityHashCode(beanFactory);
if (this.factoriesPostProcessed.contains(factoryId)) {
    throw new IllegalStateException(
            "postProcessBeanFactory already called on this post-processor against " + beanFactory);
}
this.factoriesPostProcessed.add(factoryId);
if (!this.registriesPostProcessed.contains(factoryId)) {
    // BeanDefinitionRegistryPostProcessor hook apparently not supported...
    // Simply call processConfigurationClasses lazily at this point then.
    processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
}
//给配置类产生cglib代理
//为什么需要产生cglib代理?(给AppConfig产生代理类,configDao2()方法调用了configDao1()方法)
enhanceConfigurationClasses(beanFactory);
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));

}

public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {

Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
for (String beanName : beanFactory.getBeanDefinitionNames()) {
    BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
    //判断是否是一个全注解类
    //扫描是全注解类?full和lite的关系
    if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) {
        if (!(beanDef instanceof AbstractBeanDefinition)) {
            throw new BeanDefinitionStoreException("");
        }
        else if (logger.isWarnEnabled() && beanFactory.containsSingleton(beanName)) {
            logger.warn("");
        }
        configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
    }
}
if (configBeanDefs.isEmpty()) {
    return;
}

//完成cglib代理
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
    AbstractBeanDefinition beanDef = entry.getValue();
    // If a @Configuration class gets proxied, always proxy the target class
    beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
    try {
        // Set enhanced subclass of the user-specified bean class
        Class<?> configClass = beanDef.resolveBeanClass(this.beanClassLoader);
        if (configClass != null) {
            //完成对全注解类的cglib代理
            Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
            if (configClass != enhancedClass) {
                if (logger.isDebugEnabled()) {
                    logger.debug(""));
                }
                beanDef.setBeanClass(enhancedClass);
            }
        }
    }
}

}

ConfigurationClassEnhancer

public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {

//判断是否被代理过
if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
    if (logger.isDebugEnabled()) {
        logger.debug("");
    }
    return configClass;
}
//没有被代理cglib代理
Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
if (logger.isDebugEnabled()) {
    logger.debug(String.format("");
}
return enhancedClass;

}

private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {

Enhancer enhancer = new Enhancer();
//增强父类,地球人都知道cglib是基于继承来的
enhancer.setSuperclass(configSuperClass);
//增强接口,为什么要增强接口?
//便于判断,表示一个类以及被增强了(实现BeanFactoryAware,为了获得BeanFactory对象)
enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
//不继承Factory接口
enhancer.setUseFactory(false);
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
// BeanFactoryAwareGeneratorStrategy是一个生成策略
// 主要为生成的CGLIB类中添加成员变量$$beanFactory
// 同时基于接口EnhancedConfiguration的父接口BeanFactoryAware中的setBeanFactory方法,
// 设置此变量的值为当前Context中的beanFactory,这样一来我们这个cglib代理的对象就有了beanFactory
// 有了factory就能获得对象,而不用去通过方法获得对象了,因为通过方法获得对象不能控制器过程
// 该BeanFactory的作用是在this调用时拦截该调用,并直接在beanFactory中获得目标bean
enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
//过滤方法,不能每次都去new
enhancer.setCallbackFilter(CALLBACK_FILTER);
enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
return enhancer;

}

//CALLBACK_FILTER:setCallbackFilter
private static final Callback[] CALLBACKS = new Callback[] {

    //增强方法,主要控制bean的作用域
    //(不用每一次都去调用new)
    new BeanMethodInterceptor(),
    //设置一个beanFactory
    new BeanFactoryAwareMethodInterceptor(),
    NoOp.INSTANCE

};
private static final ConditionalCallbackFilter CALLBACK_FILTER = new ConditionalCallbackFilter(CALLBACKS);

/**

  • 用于拦截@Bean方法的调用,并直接从BeanFactory中获取目标bean,而不是通过执行方法。

*/
private static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {

@Override
@Nullable
public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
            MethodProxy cglibMethodProxy) throws Throwable {

    // enhancedConfigInstance 代理
    // 通过enhancedConfigInstance中cglib生成的成员变量$$beanFactory获得beanFactory。
    ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);

    String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);

    // Determine whether this bean is a scoped-proxy
    Scope scope = AnnotatedElementUtils.findMergedAnnotation(beanMethod, Scope.class);
    if (scope != null && scope.proxyMode() != ScopedProxyMode.NO) {
        String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
        if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {
            beanName = scopedBeanName;
        }
    }
    
    if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
            factoryContainsBean(beanFactory, beanName)) {
        Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
        if (factoryBean instanceof ScopedProxyFactoryBean) {
            // Scoped proxy factory beans are a special case and should not be further proxied
        }
        else {
            // It is a candidate FactoryBean - go ahead with enhancement
            return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
        }
    }

    //一个非常牛逼的判断
    //判断到底是new 还是get
    //判断执行的方法和调用方法是不是同一个方法
    if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
        //如果是同一个方法:调用代理对象的方法,执行被代理类的方法(即configDao1()的new ConfigDao1()实例化configDao1对象)
        return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
    }
    //不是同一个方法:调用getBean方法。(即在执行configDao2()方法,调用了configDao1()方法)
    return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
}

private Object resolveBeanReference(Method beanMethod, Object[] beanMethodArgs,
        ConfigurableBeanFactory beanFactory, String beanName) {
    //判断他是否正在创建
    boolean alreadyInCreation = beanFactory.isCurrentlyInCreation(beanName);
    try {
        if (alreadyInCreation) {
            beanFactory.setCurrentlyInCreation(beanName, false);
        }
        boolean useArgs = !ObjectUtils.isEmpty(beanMethodArgs);
        if (useArgs && beanFactory.isSingleton(beanName)) {
            for (Object arg : beanMethodArgs) {
                if (arg == null) {
                    useArgs = false;
                    break;
                }
            }
        }
        //beanFactory.getBean
        //这个方法spring就写的非常牛逼,在bean实例化的会重点解析
        Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) : beanFactory.getBean(beanName));
        if (!ClassUtils.isAssignableValue(beanMethod.getReturnType(), beanInstance)) {
            if (beanInstance.equals(null)) {
                if (logger.isDebugEnabled()) {
                    logger.debug(""));
                }
                beanInstance = null;
            }
            else {
                String msg = "";
                try {
                    BeanDefinition beanDefinition = beanFactory.getMergedBeanDefinition(beanName);
                    msg += " Overriding bean of same name declared in: " + beanDefinition.getResourceDescription();
                }
                catch (NoSuchBeanDefinitionException ex) {
                    // Ignore - simply no detailed message then.
                }
                throw new IllegalStateException(msg);
            }
        }
        Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
        if (currentlyInvoked != null) {
            String outerBeanName = BeanAnnotationHelper.determineBeanNameFor(currentlyInvoked);
            beanFactory.registerDependentBean(beanName, outerBeanName);
        }
        return beanInstance;
    }
    finally {
        if (alreadyInCreation) {
            beanFactory.setCurrentlyInCreation(beanName, true);
        }
    }
    
    //判断执行的方法和调用方法是不是同一个方法
    private boolean isCurrentlyInvokedFactoryMethod(Method method) {
        Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
        return (currentlyInvoked != null && method.getName().equals(currentlyInvoked.getName()) &&
                Arrays.equals(method.getParameterTypes(), currentlyInvoked.getParameterTypes()));
    }
}

}

> 这里给加了@Configuration注解的类使用cglib动态代理产生的代理类:
>1. 主要是使用BeanMethodInterceptor类,在bean被实例化的时候,进行拦截。
>2. 怎么做到在configDao2()方法中调用了configDao1(),而configDao1没有被创建两次?
>>  主要是判断执行的方法和调用方法是不是同一个方法,即在执行configDao2()方法的时候,调用了configDao1()方法。
>>  所以在再次执行configDao1()方法时候,判断出发起调用的主方法是configDao2,即执行方法和调用方法不是同一方法。
>
>3.1 如果是同一个方法:调用代理对象的方法,执行被代理类的方法
>>       cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
>3.2 不是同一个方法:调用getBean方法
>>      return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
### spring初始化总结
#### spring的扩展点(5个)
>1. BeanPostProcessor
>>插手bean的实例过程、实例化之后,在bean没有被spring的bean容器管理之前干活。
>>经典场景:@PostConstruct、aop 
>2. BeanFactoryPostProcessor
>>spring的bean容器当中任意的一个bean被new出来之前执行,针对beanFactory来建设。
>>经典场景:ConfigurationClassPostProcessor#postProcessBeanFactory,针对配置类(@Configuration注解)加上cglib代理。
>3. BeanFactoryRegistryPostProcessor
>>是BeanFactoryPostProcessor的子类,在BeanFactoryPostProcessor之前执行?因为源码当中先遍历BeanFactoryRegistryPostProcessor(有spring提供的,还有自定义)自定义的先执行。
>>经典场景:ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry,扫描、3种import的扫描、@Bean的扫描,判断配置类是否是一个完整的配置类
>4. ImportSelector
>>通过这个方法selectImports返回一个类名(全名)数组,把他变成beanDefinition,动态添加beanDefinition(这个BeanDefinition是写死的,因为这个BeanDefinition是有spring内部生成的,我们无法改变这些BeanDefinition)
>5. ImportBeanDefinitionRegistrar
>>registerBeanDefinitions方法可以得到BeanDefinitionRegistry故而可以动态添加BeanDefinition,还可以改变BeanDefinition。
>>经典场景:mybatis的mapperScan

#### spring bean初始化结构图:
目录
相关文章
|
9天前
|
移动开发 前端开发 JavaScript
从入门到精通:H5游戏源码开发技术全解析与未来趋势洞察
H5游戏凭借其跨平台、易传播和开发成本低的优势,近年来发展迅猛。接下来,让我们深入了解 H5 游戏源码开发的技术教程以及未来的发展趋势。
|
7天前
|
存储 前端开发 JavaScript
在线教育网课系统源码开发指南:功能设计与技术实现深度解析
在线教育网课系统是近年来发展迅猛的教育形式的核心载体,具备用户管理、课程管理、教学互动、学习评估等功能。本文从功能和技术两方面解析其源码开发,涵盖前端(HTML5、CSS3、JavaScript等)、后端(Java、Python等)、流媒体及云计算技术,并强调安全性、稳定性和用户体验的重要性。
|
7天前
|
存储 监控 数据可视化
SaaS云计算技术的智慧工地源码,基于Java+Spring Cloud框架开发
智慧工地源码基于微服务+Java+Spring Cloud +UniApp +MySql架构,利用传感器、监控摄像头、AI、大数据等技术,实现施工现场的实时监测、数据分析与智能决策。平台涵盖人员、车辆、视频监控、施工质量、设备、环境和能耗管理七大维度,提供可视化管理、智能化报警、移动智能办公及分布计算存储等功能,全面提升工地的安全性、效率和质量。
|
2月前
|
XML Java 开发者
Spring底层架构核心概念解析
理解 Spring 框架的核心概念对于开发和维护 Spring 应用程序至关重要。IOC 和 AOP 是其两个关键特性,通过依赖注入和面向切面编程实现了高效的模块化和松耦合设计。Spring 容器管理着 Beans 的生命周期和配置,而核心模块为各种应用场景提供了丰富的功能支持。通过全面掌握这些核心概念,开发者可以更加高效地利用 Spring 框架开发企业级应用。
89 18
|
15天前
|
机器学习/深度学习 自然语言处理 算法
生成式 AI 大语言模型(LLMs)核心算法及源码解析:预训练篇
生成式 AI 大语言模型(LLMs)核心算法及源码解析:预训练篇
114 0
|
1月前
|
传感器 监控 安全
智慧工地云平台的技术架构解析:微服务+Spring Cloud如何支撑海量数据?
慧工地解决方案依托AI、物联网和BIM技术,实现对施工现场的全方位、立体化管理。通过规范施工、减少安全隐患、节省人力、降低运营成本,提升工地管理的安全性、效率和精益度。该方案适用于大型建筑、基础设施、房地产开发等场景,具备微服务架构、大数据与AI分析、物联网设备联网、多端协同等创新点,推动建筑行业向数字化、智能化转型。未来将融合5G、区块链等技术,助力智慧城市建设。
|
2月前
|
自然语言处理 数据处理 索引
mindspeed-llm源码解析(一)preprocess_data
mindspeed-llm是昇腾模型套件代码仓,原来叫"modelLink"。这篇文章带大家阅读一下数据处理脚本preprocess_data.py(基于1.0.0分支),数据处理是模型训练的第一步,经常会用到。
75 0
|
4月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
144 2
|
3月前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是"将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。创建型模式分为5种:单例模式、工厂方法模式抽象工厂式、原型模式、建造者模式。
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
3月前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析

热门文章

最新文章

推荐镜像

更多