Spring之环境变量配置

2023-05-16

本地配置实现原理

项目启动时准备环境

public class SpringApplication {

    public ConfigurableApplicationContext run(String... args) {
        long startTime = System.nanoTime();
        DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
        ConfigurableApplicationContext context = null;
        this.configureHeadlessProperty();
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        listeners.starting(bootstrapContext, this.mainApplicationClass);

        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            // 获取环境变量和配置数据
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
            this.configureIgnoreBeanInfo(environment);
            Banner printedBanner = this.printBanner(environment);
            context = this.createApplicationContext();
            context.setApplicationStartup(this.applicationStartup);
            this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
            this.refreshContext(context);
            this.afterRefresh(context, applicationArguments);
            Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), timeTakenToStartup);
            }

            listeners.started(context, timeTakenToStartup);
            this.callRunners(context, applicationArguments);
        } catch (Throwable var12) {
            this.handleRunFailure(context, var12, listeners);
            throw new IllegalStateException(var12);
        }

        try {
            Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
            listeners.ready(context, timeTakenToReady);
            return context;
        } catch (Throwable var11) {
            this.handleRunFailure(context, var11, (SpringApplicationRunListeners)null);
            throw new IllegalStateException(var11);
        }
    }
}

获取系统环境变量和配置数据,加载为Environment

    private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
        ConfigurableEnvironment environment = this.getOrCreateEnvironment();
        this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
        ConfigurationPropertySources.attach((Environment)environment);
        listeners.environmentPrepared(bootstrapContext, (ConfigurableEnvironment)environment);
        DefaultPropertiesPropertySource.moveToEnd((ConfigurableEnvironment)environment);
        Assert.state(!((ConfigurableEnvironment)environment).containsProperty("spring.main.environment-prefix"), "Environment prefix cannot be set via properties.");
        this.bindToSpringApplication((ConfigurableEnvironment)environment);
        if (!this.isCustomEnvironment) {
            environment = this.convertEnvironment((ConfigurableEnvironment)environment);
        }

        ConfigurationPropertySources.attach((Environment)environment);
        return (ConfigurableEnvironment)environment;
    }

listeners.environmentPrepared(bootstrapContext, (ConfigurableEnvironment)environment);

public interface PropertySourceLoader {
    String[] getFileExtensions();

    List<PropertySource<?>> load(String name, Resource resource) throws IOException;
}

spring在5个路径下(classpath/*, classpath/config/*, /*, /config/*, /config/*/*)找application.properties和application.yml配置文件。

注:默认先读取application.properties文件,如果application.properties和application.yml中有相同的属性,那么以application.properties中的值为准,一旦加载到对应的属性,后面就会跳过,不会覆盖前面加载的属性值

针对application.yml,实现类是YamlPropertySourceLoader

public class YamlPropertySourceLoader implements PropertySourceLoader {
    public YamlPropertySourceLoader() {}

    public String[] getFileExtensions() {
        return new String[]{"yml", "yaml"};
    }

    public List<PropertySource<?>> load(String name, Resource resource) throws IOException {
        if (!ClassUtils.isPresent("org.yaml.snakeyaml.Yaml", this.getClass().getClassLoader())) {
            throw new IllegalStateException("Attempted to load " + name + " but snakeyaml was not found on the classpath");
        } else {
            List<Map<String, Object>> loaded = (new OriginTrackedYamlLoader(resource)).load();
            if (loaded.isEmpty()) {
                return Collections.emptyList();
            } else {
                List<PropertySource<?>> propertySources = new ArrayList(loaded.size());

                for(int i = 0; i < loaded.size(); ++i) {
                    String documentNumber = loaded.size() != 1 ? " (document #" + i + ")" : "";
                    propertySources.add(new OriginTrackedMapPropertySource(name + documentNumber, Collections.unmodifiableMap((Map)loaded.get(i)), true));
                }

                return propertySources;
            }
        }
    }
}

针对application.properties,实现类是PropertiesPropertySourceLoader

public class PropertiesPropertySourceLoader implements PropertySourceLoader {
    private static final String XML_FILE_EXTENSION = ".xml";

    public PropertiesPropertySourceLoader() {}

    public String[] getFileExtensions() {
        return new String[]{"properties", "xml"};
    }

    public List<PropertySource<?>> load(String name, Resource resource) throws IOException {
        List<Map<String, ?>> properties = this.loadProperties(resource);
        if (properties.isEmpty()) {
            return Collections.emptyList();
        } else {
            List<PropertySource<?>> propertySources = new ArrayList(properties.size());

            for(int i = 0; i < properties.size(); ++i) {
                String documentNumber = properties.size() != 1 ? " (document #" + i + ")" : "";
                propertySources.add(new OriginTrackedMapPropertySource(name + documentNumber, Collections.unmodifiableMap((Map)properties.get(i)), true));
            }

            return propertySources;
        }
    }

    private List<Map<String, ?>> loadProperties(Resource resource) throws IOException {
        String filename = resource.getFilename();
        List<Map<String, ?>> result = new ArrayList();
        if (filename != null && filename.endsWith(".xml")) {
            result.add(PropertiesLoaderUtils.loadProperties(resource));
        } else {
            List<Document> documents = (new OriginTrackedPropertiesLoader(resource)).load();
            documents.forEach((document) -> {
                result.add(document.asMap());
            });
        }

        return result;
    }
}
public final class ConfigurationPropertySources {
    private static final String ATTACHED_PROPERTY_SOURCE_NAME = "configurationProperties";

    public static void attach(Environment environment) {
        Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
        MutablePropertySources sources = ((ConfigurableEnvironment)environment).getPropertySources();
        PropertySource<?> attached = getAttached(sources);
        if (attached == null || !isUsingSources((PropertySource)attached, sources)) {
            attached = new ConfigurationPropertySourcesPropertySource("configurationProperties", new SpringConfigurationPropertySources(sources));
        }
        sources.remove("configurationProperties");
        // 将加载了配置文件的PropertySource添加到Environment中
        sources.addFirst((PropertySource)attached);
    }
}

刷新上下文容器

public class ServletWebServerApplicationContext extends GenericWebApplicationContext implements ConfigurableWebServerApplicationContext {
    private void refreshContext(ConfigurableApplicationContext context) {
        if (this.registerShutdownHook) {
            shutdownHook.registerApplicationContext(context);
        }
        this.refresh(context);
    }

    protected void refresh(ConfigurableApplicationContext applicationContext) {
        applicationContext.refresh();
    }
}
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
    public void refresh() throws BeansException, IllegalStateException {
        synchronized(this.startupShutdownMonitor) {
            StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
            this.prepareRefresh();
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            this.prepareBeanFactory(beanFactory);

            try {
                this.postProcessBeanFactory(beanFactory);
                StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
                this.invokeBeanFactoryPostProcessors(beanFactory);
                this.registerBeanPostProcessors(beanFactory);
                beanPostProcess.end();
                this.initMessageSource();
                this.initApplicationEventMulticaster();
                this.onRefresh();
                this.registerListeners();
                this.finishBeanFactoryInitialization(beanFactory);
                this.finishRefresh();
            } catch (BeansException var10) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
                }
                this.destroyBeans();
                this.cancelRefresh(var10);
                throw var10;
            } finally {
                this.resetCommonCaches();
                contextRefresh.end();
            }

        }
    }
}

注册BeanPostProcessors,通过BeanPostProcessor修改bean的属性值

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
    protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
    }
}
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
    public Object getBean(String name) throws BeansException {
        return this.doGetBean(name, (Class)null, (Object[])null, false);
    }

    protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
                if (mbd.isSingleton()) {
                    sharedInstance = this.getSingleton(beanName, () -> {
                        try {
                            return this.createBean(beanName, mbd, args);
                        } catch (BeansException var5) {
                            this.destroySingleton(beanName);
                            throw var5;
                        }
                    });
                    beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }
    }
}
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        beanInstance = this.doCreateBean(beanName, mbdToUse, args);
        return beanInstance;
    }

    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        this.populateBean(beanName, mbd, instanceWrapper);
    }

    protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
        PropertyValues pvsToUse;
        for(Iterator var9 = this.getBeanPostProcessorCache().instantiationAware.iterator(); var9.hasNext(); pvs = pvsToUse) {
            InstantiationAwareBeanPostProcessor bp = (InstantiationAwareBeanPostProcessor)var9.next();
            pvsToUse = bp.postProcessProperties((PropertyValues)pvs, bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {
                if (filteredPds == null) {
                    filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                }
                pvsToUse = bp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);
                if (pvsToUse == null) {
                    return;
                }
            }
        }
    }
}

通过BeanPostProcessor注入bean的属性

public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
        InjectionMetadata metadata = this.findAutowiringMetadata(beanName, bean.getClass(), pvs);

        try {
            metadata.inject(bean, beanName, pvs);
            return pvs;
        } catch (BeanCreationException var6) {
            throw var6;
        } catch (Throwable var7) {
            throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", var7);
        }
    }
}
public class InjectionMetadata {
    public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
        Collection<InjectionMetadata.InjectedElement> checkedElements = this.checkedElements;
        Collection<InjectionMetadata.InjectedElement> elementsToIterate = checkedElements != null ? checkedElements : this.injectedElements;
        if (!((Collection)elementsToIterate).isEmpty()) {
            Iterator var6 = ((Collection)elementsToIterate).iterator();

            while(var6.hasNext()) {
                InjectionMetadata.InjectedElement element = (InjectionMetadata.InjectedElement)var6.next();
                element.inject(target, beanName, pvs);
            }
        }
    }
}

AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(bean, beanName, pvs) -> resolveFieldValue(field, bean, beanName) ->

bean属性注入

        protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
            Field field = (Field)this.member;
            Object value;
            if (this.cached) {
                try {
                    value = AutowiredAnnotationBeanPostProcessor.this.resolvedCachedArgument(beanName, this.cachedFieldValue);
                } catch (NoSuchBeanDefinitionException var7) {
                    value = this.resolveFieldValue(field, bean, beanName);
                }
            } else {
                // 获取字段@Value对应的值
                value = this.resolveFieldValue(field, bean, beanName);
            }

            if (value != null) {
                ReflectionUtils.makeAccessible(field);
                // 通过反射给目标字段赋值
                field.set(bean, value);
            }
        }

获取字段的值

        @Nullable
        private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
            DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
            desc.setContainingClass(bean.getClass());
            Set<String> autowiredBeanNames = new LinkedHashSet(1);
            Assert.state(AutowiredAnnotationBeanPostProcessor.this.beanFactory != null, "No BeanFactory available");
            TypeConverter typeConverter = AutowiredAnnotationBeanPostProcessor.this.beanFactory.getTypeConverter();

            Object value;
            try {
                // 获取字段依赖的属性值
                value = AutowiredAnnotationBeanPostProcessor.this.beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
            } catch (BeansException var12) {
                throw new UnsatisfiedDependencyException((String)null, beanName, new InjectionPoint(field), var12);
            }

            synchronized(this) {
                if (!this.cached) {
                    Object cachedFieldValue = null;
                    if (value != null || this.required) {
                        cachedFieldValue = desc;
                        AutowiredAnnotationBeanPostProcessor.this.registerDependentBeans(beanName, autowiredBeanNames);
                        if (autowiredBeanNames.size() == 1) {
                            String autowiredBeanName = (String)autowiredBeanNames.iterator().next();
                            if (AutowiredAnnotationBeanPostProcessor.this.beanFactory.containsBean(autowiredBeanName) && AutowiredAnnotationBeanPostProcessor.this.beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                                cachedFieldValue = new AutowiredAnnotationBeanPostProcessor.ShortcutDependencyDescriptor(desc, autowiredBeanName, field.getType());
                            }
                        }
                    }

                    this.cachedFieldValue = cachedFieldValue;
                    this.cached = true;
                }

                return value;
            }
        }

获取注入依赖

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
    @Nullable
    public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
        descriptor.initParameterNameDiscovery(this.getParameterNameDiscoverer());
        if (Optional.class == descriptor.getDependencyType()) {
            return this.createOptionalDependency(descriptor, requestingBeanName);
        } else if (ObjectFactory.class != descriptor.getDependencyType() && ObjectProvider.class != descriptor.getDependencyType()) {
            if (javaxInjectProviderClass == descriptor.getDependencyType()) {
                return (new DefaultListableBeanFactory.Jsr330Factory()).createDependencyProvider(descriptor, requestingBeanName);
            } else {
                Object result = this.getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);
                if (result == null) {
                    result = this.doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
                }

                return result;
            }
        } else {
            return new DefaultListableBeanFactory.DependencyObjectProvider(descriptor, requestingBeanName);
        }
    }
}
    @Nullable
    public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
        InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);

        Object var23;
        try {
            Object shortcut = descriptor.resolveShortcut(this);
            if (shortcut != null) {
                Object var20 = shortcut;
                return var20;
            }

            Class<?> type = descriptor.getDependencyType();
            Object value = this.getAutowireCandidateResolver().getSuggestedValue(descriptor);
            Object var11;
            if (value == null) {
                Object multipleBeans = this.resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
                if (multipleBeans != null) {
                    var23 = multipleBeans;
                    return var23;
                }

                Map<String, Object> matchingBeans = this.findAutowireCandidates(beanName, type, descriptor);
                if (matchingBeans.isEmpty()) {
                    if (this.isRequired(descriptor)) {
                        this.raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
                    }
                    var11 = null;
                    return var11;
                }

                Object instanceCandidate;
                Object result;
                String autowiredBeanName;
                if (matchingBeans.size() > 1) {
                    autowiredBeanName = this.determineAutowireCandidate(matchingBeans, descriptor);
                    if (autowiredBeanName == null) {
                        if (!this.isRequired(descriptor) && this.indicatesMultipleBeans(type)) {
                            result = null;
                            return result;
                        }
                        result = descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
                        return result;
                    }

                    instanceCandidate = matchingBeans.get(autowiredBeanName);
                } else {
                    Entry<String, Object> entry = (Entry)matchingBeans.entrySet().iterator().next();
                    autowiredBeanName = (String)entry.getKey();
                    instanceCandidate = entry.getValue();
                }

                if (autowiredBeanNames != null) {
                    autowiredBeanNames.add(autowiredBeanName);
                }
                if (instanceCandidate instanceof Class) {
                    instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
                }

                result = instanceCandidate;
                if (instanceCandidate instanceof NullBean) {
                    if (this.isRequired(descriptor)) {
                        this.raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
                    }
                    result = null;
                }

                if (!ClassUtils.isAssignableValue(type, result)) {
                    throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
                }
                Object var14 = result;
                return var14;
            }

            if (value instanceof String) {
                // 获取bean注入的属性值
                String strVal = this.resolveEmbeddedValue((String)value);
                BeanDefinition bd = beanName != null && this.containsBean(beanName) ? this.getMergedBeanDefinition(beanName) : null;
                value = this.evaluateBeanDefinitionString(strVal, bd);
            }

            TypeConverter converter = typeConverter != null ? typeConverter : this.getTypeConverter();
            try {
                var23 = converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
            } catch (UnsupportedOperationException var18) {
                var11 = descriptor.getField() != null ? converter.convertIfNecessary(value, type, descriptor.getField()) : converter.convertIfNecessary(value, type, descriptor.getMethodParameter());
                return var11;
            }
        } finally {
            ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
        }

        return var23;
    }

AbstractBeanFactory.resolveEmbeddedValue(value)

根据@Value注解的key获取对应的值

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
    @Nullable
    public String resolveEmbeddedValue(@Nullable String value) {
        if (value == null) {
            return null;
        } else {
            String result = value;
            Iterator var3 = this.embeddedValueResolvers.iterator();

            do {
                if (!var3.hasNext()) {
                    return result;
                }

                StringValueResolver resolver = (StringValueResolver)var3.next();
                result = resolver.resolveStringValue(result);
            } while(result != null);

            return null;
        }
    }
}

最后通过反射给目标字段赋值

public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
    private class AutowiredFieldElement extends InjectedElement {
        protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
            Field field = (Field)this.member;
            Object value;
            if (this.cached) {
                try {
                    value = AutowiredAnnotationBeanPostProcessor.this.resolvedCachedArgument(beanName, this.cachedFieldValue);
                } catch (NoSuchBeanDefinitionException var7) {
                    value = this.resolveFieldValue(field, bean, beanName);
                }
            } else {
                // 获取字段@Value对应的值
                value = this.resolveFieldValue(field, bean, beanName);
            }

            if (value != null) {
                ReflectionUtils.makeAccessible(field);
                // 通过反射给目标字段赋值
                field.set(bean, value);
            }
        }
    }
}

field.set(bean, value);

public final class Field extends AccessibleObject implements Member {
    @CallerSensitive
    public void set(Object obj, Object value)
        throws IllegalArgumentException, IllegalAccessException
    {
        if (!override) {
            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
                Class<?> caller = Reflection.getCallerClass();
                checkAccess(caller, clazz, obj, modifiers);
            }
        }
        getFieldAccessor(obj).set(obj, value);
    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring之环境变量配置 的相关文章

随机推荐

  • 已知一指针p,你可以确定该指针是否指向一个有效的对象吗?如果可以,如何确定?如果不可以,请说明原因。

    这个问题我的思路是 xff1a 首先用 p将其值输出来 xff0c 如果编译器报错 xff0c 证明p指向一个无效的对象 xff0c 要么p 61 0要么p未进行初始化 xff0c 此时可以用if p 61 61 NULL 进行判断即可 x
  • opencv学习_10 (图像和轮廓的匹配(hu矩))

    图像和轮廓的匹配 hu矩 1 hu矩的概念 xff0c 我也总结了但是我不过多的阐述 xff0c 因为我也不是太理解 xff0c 只知道它具有平移 xff0c 旋转 xff0c 尺度不变性 xff0c 详细见别人的这篇 blog xff1a
  • opencv学习_11 (模板匹配(包括单模板和多模板))

    模板匹配 在一幅图像中匹配与模板相似的单个或者多个目标 1 目标匹配函数 xff1a cvMatchTemplate const CvArr image constCvArr templ CvArr result int method Im
  • opencv学习_11 (moravec角点检测及缺点)

    1 首先我们来看三幅图片理解什么是角点 xff1a 我们在图片以某像素点为中心 xff0c 取一窗口 xff0c 当窗口向各个方向移动时 xff0c 其内部灰度值变化不是很明显 xff0c 则该点即处在平坦区域 如左边图 xff1b 当其内
  • 2013学习总结

    时间飞逝 xff0c 很快又要过年了 xff0c 马上就要回家了 xff0c 2013年工作也接近尾声了 下面好好总结下2013 学习与工作 lt 1 gt 863农产品推荐系统 一个字形容 xff1a 水 可能国家项目都是这样的 不管怎样
  • 机器学习实战笔记2(k-近邻算法)

    1 xff1a 算法简单描述 给定训练数据样本和标签 xff0c 对于某测试的一个样本数据 xff0c 选择距离其最近的k个训练样本 xff0c 这k个训练样本中所属类别最多的类即为该测试样本的预测标签 简称kNN 通常k是不大于20的整数
  • 可导一定连续,连续不一定可导

    今天在群里面看到大家发了这句可导一定连续 xff0c 连续不一定可导 大家应该都很熟悉 xff0c 包括我自己 xff0c 但是真正理解有多少呢 xff0c 我当时就没想明白 xff0c 中午吃饭的时候也在想 xff0c 最后还是想明白了
  • 【GEEK】win10下cmd美化

    win10下cmd美化 xff0c 没任何技术含量但是很实用 如果你也讨厌cmd默认的简陋的界面 xff0c 想简单美化一下 xff0c 可以参考本文 1 设置背景色 字体颜色 标题栏 属性 颜色 xff0c 选择 屏幕文字 屏幕背景 xf
  • PCA降维简介

    PCA 全称为 principal component analysis xff0c 即主成成分分析 xff0c 用于降维 对数据进行降维有很多原因 比如 xff1a 1 xff1a 使得数据更易显示 xff0c 更易懂 2 xff1a 降
  • 相似图片搜索原理一(ahash—c++实现)

    ahash xff0c 全称叫做 average hash 应该是 phash perceptual hash 感知哈希 算法的一种 是基于图像内容搜索最简单的一种 search image by image xff0c 因此也有很多的局限
  • BP算法与公式推导

    BP backpropgationalgorithm xff1a 后向传导算法 xff0c 顾名思义就是从神经网络的输出 顶层 到输入 底层 进行求解 那么求解什么呢 xff0c 求解的就是神经网络中的参数的导数 xff0c 即参数梯度方向
  • CNN公式推导

    CNN公式推导 1 前言 在看此blog之前 xff0c 请确保已经看懂我的前两篇blog 深度学习笔记1 卷积神经网络 和 BP算法与公式推导 并且已经看过文献 1 的论文 Notes on Convolutional Neural Ne
  • 简记ReNet

    ResNet 论文给出了Resnet有3中类型 xff0c ResNet50 res3 res4 res6 res3 xff0c ResNet101 res3 res4 res23 res3 和ResNet152 res3 res4 res
  • triplet loss的原理及caffe代码

    1 xff1a triplet loss的原理及梯度推到 http blog csdn net tangwei2014 article details 46788025 2 xff1a triplet loss如何增加到caffe中 xff
  • object detection资料汇总

    转自 xff1a https handong1587 github io deep learning 2015 10 09 object detection html Jump to LeaderboardPapers R CNNMulti
  • 离职小记~~~

    这个月作出的最重要的决定 离职 对于已工作的人来说 xff0c 离职就是跳槽 xff0c 特别是对于我们计算机专业 xff0c 简简单单的一封辞职信 xff0c 等个半月 xff0c 办完手续 xff0c 一切OK xff0c 而且貌似越跳
  • C#控件编程详解之按钮控件

    摘要 xff1a 控件编程系列讲解之按钮控件 xff0c 以自身学习经历详解按钮控件的使用方法 编程语言 xff1a C 编程环境 xff1a Visual Studio 2019 目录 按钮控件属性 xff08 成员 xff09 详解 布
  • synchronized锁(方法锁, 代码块锁)

    synchronized 锁可以解决线程安全问题 xff0c 但是相应的 xff0c 只要是锁 xff0c 就会带来性能开销 xff0c 所以尽可能减小锁的范围尤为重要 synchronized锁无非修饰普通方法 xff0c 修饰静态方法
  • 骁龙855 plus的存在意义有限,高通5G芯片较对手落后

    近日高通突然发布了一款特别的芯片骁龙855 plus xff0c 让人可惜的是这并非是一款5G手机SOC芯片 xff0c 而仅仅是在骁龙855基础上提升性能的芯片 xff0c 在5G已商用之际推出的这款芯片非但没能提升高通的影响力 xff0
  • Spring之环境变量配置

    本地配置实现原理 项目启动时准备环境 public class SpringApplication public ConfigurableApplicationContext run String args long startTime 6