zoukankan      html  css  js  c++  java
  • Spring Boot 运行原理

    https://www.jianshu.com/p/23f504713b94

    核心注解

    打开上面任意一个AutoConfiguration文件,一般都有下面的条件注解,在spring-boot-autoconfigure-1.5.3.RELEASE.jar的org.springframework.boot.autoconfigure.condition包下条件注解如下:

    • @ConditionalOnBean:当前容器有指定Bean的条件下。
    • @ConditionalOnClass:当前类路径下有指定的类的条件下。
    • @ConditionalOnExpression:基于SpEL表达式作为判断条件。
    • @ConditionalOnJava:基于JVM版本作为判断条件。
    • @ConditionalOnJndi:在JNDI存在的条件下查找指定的位置。
    • @ConditionalOnMissingBean:当容器里没有指定Bean的情况下。
    • @ConditionalOnMissingClass:当类路径下没有指定的类的条件下。
    • @ConditionalOnNotWebApplication:当前项目不是WEB项目的条件下。
    • @ConditionalOnProperty:指定属性是否有指定的值。
    • @ConditionalOnResource:类路径是否有指定的值。
    • @ConditionalOnSingleCandidate:当指定Bean在容器中只有一个,或者虽然有多个但 是指定首选的Bean。
    • @ConditionalOnWebApplication:当前项目是WEB项目的条件下。

    这些注解都组合了@Conditional元注解,只是使用了不同的条件(Conditional),Spring 条件注解(@Conditional)我们介绍过根据不同条件创建不同Bean。

    简单分析一下@ConditionalOnWebApplication注解:

    package org.springframework.boot.autoconfigure.condition;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    import org.springframework.context.annotation.Conditional;
    
    @Target({ ElementType.TYPE, ElementType.METHOD })
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Conditional(OnWebApplicationCondition.class)
    public @interface ConditionalOnWebApplication {
    }
    
    

    从源码我们可以看出,此注解使用的条件是OnWebApplicationCondition类,下面我们看看这个类是怎么构造的:

    package org.springframework.boot.autoconfigure.condition;
    
    import org.springframework.context.annotation.Condition;
    import org.springframework.context.annotation.ConditionContext;
    import org.springframework.core.Ordered;
    import org.springframework.core.annotation.Order;
    import org.springframework.core.type.AnnotatedTypeMetadata;
    import org.springframework.util.ClassUtils;
    import org.springframework.util.ObjectUtils;
    import org.springframework.web.context.WebApplicationContext;
    import org.springframework.web.context.support.StandardServletEnvironment;
    
    @Order(Ordered.HIGHEST_PRECEDENCE + 20)
    class OnWebApplicationCondition extends SpringBootCondition {
    
        private static final String WEB_CONTEXT_CLASS = "org.springframework.web.context."
                + "support.GenericWebApplicationContext";
    
        @Override
        public ConditionOutcome getMatchOutcome(ConditionContext context,
                AnnotatedTypeMetadata metadata) {
            boolean webApplicationRequired = metadata
                    .isAnnotated(ConditionalOnWebApplication.class.getName());
            ConditionOutcome webApplication = isWebApplication(context, metadata);
    
            if (webApplicationRequired && !webApplication.isMatch()) {
                return ConditionOutcome.noMatch(webApplication.getMessage());
            }
    
            if (!webApplicationRequired && webApplication.isMatch()) {
                return ConditionOutcome.noMatch(webApplication.getMessage());
            }
    
            return ConditionOutcome.match(webApplication.getMessage());
        }
    
        private ConditionOutcome isWebApplication(ConditionContext context,
                AnnotatedTypeMetadata metadata) {
    
            if (!ClassUtils.isPresent(WEB_CONTEXT_CLASS, context.getClassLoader())) {
                return ConditionOutcome.noMatch("web application classes not found");
            }
    
            if (context.getBeanFactory() != null) {
                String[] scopes = context.getBeanFactory().getRegisteredScopeNames();
                if (ObjectUtils.containsElement(scopes, "session")) {
                    return ConditionOutcome.match("found web application 'session' scope");
                }
            }
    
            if (context.getEnvironment() instanceof StandardServletEnvironment) {
                return ConditionOutcome
                        .match("found web application StandardServletEnvironment");
            }
    
            if (context.getResourceLoader() instanceof WebApplicationContext) {
                return ConditionOutcome.match("found web application WebApplicationContext");
            }
    
            return ConditionOutcome.noMatch("not a web application");
        }
    
    }
    
    

    从isWebApplication方法可以看出,判断条件是:

    1. GenericWebApplicationContext是否在类路径中;
    2. 容器中是否有名为session的scope;
    3. 当前容器的Enviroment是否为StandardServletEnvironment;
    4. 当前的ResourceLoader是否是WebApplicationContext(ResourceLoader是ApplicationContext的顶级接口之一);
    5. 我们需要构建ConditionOutcome类的对象来帮助我们,最终通过ConditionOutcome.isMatch方法返回值来确定条件。
  • 相关阅读:
    Qt学习之路,part1
    1.获取状态栏的高度
    如何在Android Studio中上传代码到Gitee上
    关于类图
    外观模式
    关于类的实例
    SharedPreference中关于editor.apply()和editor.commit()
    活动的4种启动模式
    unittest中case批量管理
    unittest使用
  • 原文地址:https://www.cnblogs.com/kelelipeng/p/11994024.html
Copyright © 2011-2022 走看看