作者:微信小助手
发布时间:2024-01-24T22:47:17
成长不是瞬间的华丽转身 而是每天坚持努力的积累 STRAT 乘风破浪 | 直挂云帆 本篇来聊聊Springboot中的条件注解,这些条件注解使得开发者能够根据运行时环境的不同,动态的选择性地加载或配置一些 Bean 或组件。通过合理使用条件注解,可以实现更灵活和可配置的应用程序。 @ConditionalOnBean和@ConditionalOnClass的底层实现应该是差不多的,一个是判断Bean存不存在,一个是判断类存不存在,事实上也确实差不多。
@ConditionalOnBean和@ConditionalOnMissingBean对应的都是OnBeanCondition类, OnBeanCondition类也是继承了SpringBootCondition,所以SpringBootCondition类中的getMatchOutcome方法才是匹配逻辑。 @ConditionalOnMissingBean的作用是用来判断某个Bean是否缺失,如果不存在某个Bean,那就符合该条件。
</ul>
<pre class="code-snippet__js" data-lang="java"><code><span class="code-snippet_outer"><span class="code-snippet__meta">@Override</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__function"><span class="code-snippet__keyword">public</span> <span class="code-snippet__keyword">final</span> <span class="code-snippet__keyword">boolean</span> <span class="code-snippet__title">matches</span><span class="code-snippet__params">(ConditionContext context, AnnotatedTypeMetadata metadata)</span> </span>{</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 针对每个条件注解进行条件判断</span></span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 条件注解写在了哪个类上,或哪个方法上</span></span></code><code><span class="code-snippet_outer"> String classOrMethodName = getClassOrMethodName(metadata);</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">try</span> {</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 条件的判断结果</span></span></code><code><span class="code-snippet_outer"> ConditionOutcome outcome = getMatchOutcome(context, metadata);</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 如果log的日志级别为trace,那就直接记录当前条件的判断结果</span></span></code><code><span class="code-snippet_outer"> logOutcome(classOrMethodName, outcome);</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 将判断结果记录到ConditionEvaluationReport中</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">//ConditionEvaluationReportLoggingListener会在收到ContextRefreshedEvent事件后把判断结果用日志的方式打印出来</span></span></code><code><span class="code-snippet_outer"> recordEvaluation(context, classOrMethodName, outcome);</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">return</span> outcome.isMatch();</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">catch</span> (NoClassDefFoundError ex) {</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">throw</span> <span class="code-snippet__keyword">new</span> IllegalStateException(<span class="code-snippet__string">"Could not evaluate condition on "</span> + classOrMethodName + <span class="code-snippet__string">" due to "</span></span></code><code><span class="code-snippet_outer"> + ex.getMessage() + <span class="code-snippet__string">" not found. Make sure your own configuration does not rely on "</span></span></code><code><span class="code-snippet_outer"> + <span class="code-snippet__string">"that class. This can also happen if you are "</span></span></code><code><span class="code-snippet_outer"> + <span class="code-snippet__string">"@ComponentScanning a springframework package (e.g. if you "</span></span></code><code><span class="code-snippet_outer"> + <span class="code-snippet__string">"put a @ComponentScan in the default package by mistake)"</span>, ex);</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">catch</span> (RuntimeException ex) {</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">throw</span> <span class="code-snippet__keyword">new</span> IllegalStateException(<span class="code-snippet__string">"Error processing condition on "</span> + getName(metadata), ex);</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer">}</span></code></pre>
</section>
</section>
</section>
</section>
</section>
</section>
</section>
</section>
</ul>
<pre class="code-snippet__js" data-lang="kotlin"><code><span class="code-snippet_outer"><span class="code-snippet__keyword">public</span> ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {</span></code><code><span class="code-snippet_outer"> ClassLoader classLoader = context.getClassLoader();</span></code><code><span class="code-snippet_outer"> ConditionMessage matchMessage = ConditionMessage.empty();</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 拿到ConditionalOnClass注解中的value值,也就是要判断是否存在的类名</span></span></code><code><span class="code-snippet_outer"> List<String> onClasses = getCandidates(metadata, ConditionalOnClass.<span class="code-snippet__keyword">class</span>);</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">if</span> (onClasses != <span class="code-snippet__literal">null</span>) {</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 判断onClasses中不存在的类</span></span></code><code><span class="code-snippet_outer"> List<String> missing = filter(onClasses, ClassNameFilter.MISSING, classLoader);</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 如果有缺失的类,那就表示不匹配</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">if</span> (!missing.isEmpty()) {</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">return</span> ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnClass.<span class="code-snippet__keyword">class</span>)</span></code><code><span class="code-snippet_outer"> .didNotFind(<span class="code-snippet__string">"required class"</span>, <span class="code-snippet__string">"required classes"</span>).items(Style.QUOTE, missing));</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 否则就表示匹配</span></span></code><code><span class="code-snippet_outer"> matchMessage = matchMessage.andCondition(ConditionalOnClass.<span class="code-snippet__keyword">class</span>)</span></code><code><span class="code-snippet_outer"> .found(<span class="code-snippet__string">"required class"</span>, <span class="code-snippet__string">"required classes"</span>)</span></code><code><span class="code-snippet_outer"> .items(Style.QUOTE, filter(onClasses, ClassNameFilter.PRESENT, classLoader));</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 和上面类似,只不过是判断onMissingClasses是不是全部缺失,如果是则表示匹配</span></span></code><code><span class="code-snippet_outer"> List<String> onMissingClasses = getCandidates(metadata, ConditionalOnMissingClass.<span class="code-snippet__keyword">class</span>);</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">if</span> (onMissingClasses != <span class="code-snippet__literal">null</span>) {</span></code><code><span class="code-snippet_outer"> List<String> present = filter(onMissingClasses, ClassNameFilter.PRESENT, classLoader);</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">if</span> (!present.isEmpty()) {</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">return</span> ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnMissingClass.<span class="code-snippet__keyword">class</span>)</span></code><code><span class="code-snippet_outer"> .found(<span class="code-snippet__string">"unwanted class"</span>, <span class="code-snippet__string">"unwanted classes"</span>).items(Style.QUOTE, present));</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"> matchMessage = matchMessage.andCondition(ConditionalOnMissingClass.<span class="code-snippet__keyword">class</span>)</span></code><code><span class="code-snippet_outer"> .didNotFind(<span class="code-snippet__string">"unwanted class"</span>, <span class="code-snippet__string">"unwanted classes"</span>)</span></code><code><span class="code-snippet_outer"> .items(Style.QUOTE, filter(onMissingClasses, ClassNameFilter.MISSING, classLoader));</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">return</span> ConditionOutcome.match(matchMessage);</span></code><code><span class="code-snippet_outer">}</span></code></pre>
</section>
<section data-tools="135编辑器" data-id="7">
<section style="padding-left: 10px;border-left: 5px solid rgb(170, 170, 170);margin: 10px auto;">
<section style="font-size: 13px;letter-spacing: 1px;line-height: 1.75em;color: rgba(102, 102, 102, 0.8);">
<section data-role="list">
<ul class="list-paddingleft-1" style="padding-left: 30px;list-style-position: outside;margin-left: 8px;margin-right: 8px;">
<li style="font-size: 15px;color: rgb(96, 96, 96);letter-spacing: 1px;">
<section style="color: rgb(102, 102, 102);font-size: 14px;letter-spacing: 1.5px;caret-color: red;margin-top: 8px;margin-bottom: 8px;line-height: 1.75em;">
<span style="font-size: 15px;caret-color: red;color: rgb(96, 96, 96);letter-spacing: 1px;">获取ConditionalOnClass注解中的value值。</span>
<ne-clipboard source="https%3A%2F%2Fwww.yuque.com%2Fdream_lsj%2Fyddpep%2Fpunmt1zhmirb2y8x%23Bvjvx"></ne-clipboard>
</section></li>
<li style="font-size: 15px;color: rgb(96, 96, 96);letter-spacing: 1px;">
<section style="margin-top: 8px;margin-bottom: 8px;line-height: 1.75em;">
<span style="font-size: 15px;color: rgb(96, 96, 96);letter-spacing: 1px;">判断是否存在不配的类,判断逻辑为</span>
<span style="font-size: 15px;letter-spacing: 1px;color: rgb(255, 76, 0);"> Class.<em>forName</em>(className);</span>
<span style="font-size: 15px;color: rgb(96, 96, 96);letter-spacing: 1px;"> 存在就会直接返回。</span>
</section></li>
<li style="font-size: 15px;color: rgb(96, 96, 96);letter-spacing: 1px;">
<section style="margin-top: 8px;margin-bottom: 8px;line-height: 1.75em;">
<span style="font-size: 15px;color: rgb(96, 96, 96);letter-spacing: 1px;">不存在就会获取ConditionalOnMissingClass注解中的value值,然后处理逻辑与前面一直。</span>
</section></li>
</ul>
</section>
<section typography="classic" style="height: 0px;overflow: hidden;">
<br>
</section>
</section>
</section>
</section>
<section typography="classic">
<section style="min-height: 24px;margin: 24px 8px;line-height: 1.75em;">
<span style="font-size: 15px;color: rgb(96, 96, 96);letter-spacing: 1px;">Spring中会去每个注解的解析,但是springBoot中会</span>
<span style="font-size: 15px;letter-spacing: 1px;color: rgb(255, 76, 0);">提前将@ConditionalOnClass与@ConditionalOnClass</span>
<span style="font-size: 15px;color: rgb(96, 96, 96);letter-spacing: 1px;">一起解析,如果发现不匹配能够快速的处理,但是如果都成立,那么这个回去重复执行。</span>
</section>
</section>
</section>
</ul>
<pre class="code-snippet__js" data-lang="kotlin"><code><span class="code-snippet_outer"><span class="code-snippet__meta">@Override</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">public</span> ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {</span></code><code><span class="code-snippet_outer"> ConditionMessage matchMessage = ConditionMessage.empty();</span></code><code><span class="code-snippet_outer"> MergedAnnotations annotations = metadata.getAnnotations();</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 如果存在ConditionalOnBean注解</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">if</span> (annotations.isPresent(ConditionalOnBean.<span class="code-snippet__keyword">class</span>)) {</span></code><code><span class="code-snippet_outer"> Spec<ConditionalOnBean> spec = new Spec<>(context, metadata, annotations, ConditionalOnBean.<span class="code-snippet__keyword">class</span>);</span></code><code><span class="code-snippet_outer"> MatchResult matchResult = getMatchingBeans(context, spec);</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 如果某个Bean不存在</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">if</span> (!matchResult.isAllMatched()) {</span></code><code><span class="code-snippet_outer"> String reason = createOnBeanNoMatchReason(matchResult);</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">return</span> ConditionOutcome.noMatch(spec.message().because(reason));</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 所有Bean都存在</span></span></code><code><span class="code-snippet_outer"> matchMessage = spec.message(matchMessage).found(<span class="code-snippet__string">"bean"</span>, <span class="code-snippet__string">"beans"</span>).items(Style.QUOTE, matchResult.getNamesOfAllMatches());</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 如果存在ConditionalOnSingleCandidate注解</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">if</span> (metadata.isAnnotated(ConditionalOnSingleCandidate.<span class="code-snippet__keyword">class</span>.getName())) {</span></code><code><span class="code-snippet_outer"> Spec<ConditionalOnSingleCandidate> spec = new SingleCandidateSpec(context, metadata, annotations);</span></code><code><span class="code-snippet_outer"> MatchResult matchResult = getMatchingBeans(context, spec);</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// Bean不存在</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">if</span> (!matchResult.isAllMatched()) {</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">return</span> ConditionOutcome.noMatch(spec.message().didNotFind(<span class="code-snippet__string">"any beans"</span>).atAll());</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// Bean存在</span></span></code><code><span class="code-snippet_outer"> Set<String> allBeans = matchResult.getNamesOfAllMatches();</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 如果只有一个</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">if</span> (allBeans.size() == <span class="code-snippet__number">1</span>) {</span></code><code><span class="code-snippet_outer"> matchMessage = spec.message(matchMessage).found(<span class="code-snippet__string">"a single bean"</span>).items(Style.QUOTE, allBeans);</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">else</span> {</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 如果有多个</span></span></code><code><span class="code-snippet_outer"> List<String> primaryBeans = getPrimaryBeans(context.getBeanFactory(), allBeans, spec.getStrategy() == SearchStrategy.ALL);</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 没有主Bean,那就不匹配</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">if</span> (primaryBeans.isEmpty()) {</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">return</span> ConditionOutcome.noMatch(</span></code><code><span class="code-snippet_outer"> spec.message().didNotFind(<span class="code-snippet__string">"a primary bean from beans"</span>).items(Style.QUOTE, allBeans));</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 有多个主Bean,那就不匹配</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">if</span> (primaryBeans.size() > <span class="code-snippet__number">1</span>) {</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">return</span> ConditionOutcome</span></code><code><span class="code-snippet_outer"> .noMatch(spec.message().found(<span class="code-snippet__string">"multiple primary beans"</span>).items(Style.QUOTE, primaryBeans));</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 只有一个主Bean</span></span></code><code><span class="code-snippet_outer"> matchMessage = spec.message(matchMessage)</span></code><code><span class="code-snippet_outer"> .found(<span class="code-snippet__string">"a single primary bean '"</span> + primaryBeans.<span class="code-snippet__keyword">get</span>(<span class="code-snippet__number">0</span>) + <span class="code-snippet__string">"' from beans"</span>)</span></code><code><span class="code-snippet_outer"> .items(Style.QUOTE, allBeans);</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 存在ConditionalOnMissingBean注解</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">if</span> (metadata.isAnnotated(ConditionalOnMissingBean.<span class="code-snippet__keyword">class</span>.getName())) {</span></code><code><span class="code-snippet_outer"> Spec<ConditionalOnMissingBean> spec = new Spec<>(context, metadata, annotations,</span></code><code><span class="code-snippet_outer"> ConditionalOnMissingBean.<span class="code-snippet__keyword">class</span>);</span></code><code><span class="code-snippet_outer"> MatchResult matchResult = getMatchingBeans(context, spec);</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">//有任意一个Bean存在,那就条件不匹配</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">if</span> (matchResult.isAnyMatched()) {</span></code><code><span class="code-snippet_outer"> String reason = createOnMissingBeanNoMatchReason(matchResult);</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">return</span> ConditionOutcome.noMatch(spec.message().because(reason));</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 都不存在在,则匹配</span></span></code><code><span class="code-snippet_outer"> matchMessage = spec.message(matchMessage).didNotFind(<span class="code-snippet__string">"any beans"</span>).atAll();</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">return</span> ConditionOutcome.match(matchMessage);</span></code><code><span class="code-snippet_outer">}</span></code></pre>
</section>
<section data-tools="135编辑器" data-id="7">
<section style="padding-left: 10px;border-left: 5px solid rgb(170, 170, 170);margin: 10px auto;">
<section style="font-size: 13px;letter-spacing: 1px;line-height: 1.75em;color: rgba(102, 102, 102, 0.8);">
<section data-role="list">
<ul class="list-paddingleft-1" style="padding-left: 30px;list-style-position: outside;margin-left: 8px;margin-right: 8px;">
<li style="font-size: 15px;color: rgb(96, 96, 96);letter-spacing: 1px;">
<section style="color: rgb(102, 102, 102);font-size: 14px;letter-spacing: 1.5px;caret-color: red;margin-top: 8px;margin-bottom: 8px;line-height: 1.75em;">
<span style="caret-color: red;font-size: 15px;letter-spacing: 1px;color: rgb(255, 76, 0);">当前在解析的类或方法上</span>
<span style="caret-color: red;font-size: 15px;letter-spacing: 1px;color: rgb(96, 96, 96);">,</span>
<span style="caret-color: red;font-size: 15px;letter-spacing: 1px;color: rgb(96, 96, 96);">是否有@ConditionalOnBean注解,如果有则生成对应的Spec对象,该对象中包含了 用户指定的,要判断的是否存在的Bean的类型。</span>
</section></li>
<li style="font-size: 15px;color: rgb(96, 96, 96);letter-spacing: 1px;">
<section style="color: rgb(102, 102, 102);font-size: 14px;letter-spacing: 1.5px;caret-color: red;margin-top: 8px;margin-bottom: 8px;line-height: 1.75em;">
<span style="caret-color: red;font-size: 15px;letter-spacing: 1px;color: rgb(96, 96, 96);">调用</span>
<span style="caret-color: red;font-size: 15px;letter-spacing: 1px;color: rgb(255, 76, 0);">getMatchingBeans方法进行条件判断</span>
<span style="caret-color: red;font-size: 15px;letter-spacing: 1px;color: rgb(96, 96, 96);"> 。</span>
</section></li>
<li style="font-size: 15px;color: rgb(96, 96, 96);letter-spacing: 1px;">
<section style="color: rgb(102, 102, 102);font-size: 14px;letter-spacing: 1.5px;caret-color: red;margin-top: 8px;margin-bottom: 8px;line-height: 1.75em;">
<span style="caret-color: red;font-size: 15px;letter-spacing: 1px;color: rgb(96, 96, 96);">只要判断出来某一个Bean不存在,则return,表示条件不匹配 。</span>
</section></li>
<li style="font-size: 15px;color: rgb(96, 96, 96);letter-spacing: 1px;">
<section style="color: rgb(102, 102, 102);font-size: 14px;letter-spacing: 1.5px;caret-color: red;margin-top: 8px;margin-bottom: 8px;line-height: 1.75em;">
<span style="caret-color: red;font-size: 15px;letter-spacing: 1px;color: rgb(96, 96, 96);">只要所有Bean都存在,则继续执行下面代码 。</span>
</section></li>
<li style="font-size: 15px;color: rgb(96, 96, 96);letter-spacing: 1px;">
<section style="color: rgb(102, 102, 102);font-size: 14px;letter-spacing: 1.5px;caret-color: red;margin-top: 8px;margin-bottom: 8px;line-height: 1.75em;">
<span style="caret-color: red;font-size: 15px;letter-spacing: 1px;color: rgb(255, 76, 0);">在解析的类或方法上是否有@ConditionalOnSingleCandidate注解</span>
<span style="caret-color: red;font-size: 15px;letter-spacing: 1px;color: rgb(96, 96, 96);">,如果有则生成对应的 SingleCandidateSpec对象,该对象中包含了用户指定的,要判断的是否存在的Bean的类型(只能指定一个类 型),并且该类型的Bean只能有一个。</span>
</section></li>
<li style="font-size: 15px;color: rgb(96, 96, 96);letter-spacing: 1px;">
<section style="color: rgb(102, 102, 102);font-size: 14px;letter-spacing: 1.5px;caret-color: red;margin-top: 8px;margin-bottom: 8px;line-height: 1.75em;">
<span style="caret-color: red;font-size: 15px;letter-spacing: 1px;color: rgb(255, 76, 0);">调用getMatchingBeans方法进行条件判断</span>
<span style="caret-color: red;font-size: 15px;letter-spacing: 1px;color: rgb(96, 96, 96);">。</span>
</section></li>
</ul>
</section>
</section>
</section>
</section>
</section>
</ul>
<pre class="code-snippet__js" data-lang="ruby"><code><span class="code-snippet_outer">@Configuration(proxyBeanMethods = <span class="code-snippet__literal">false</span>)</span></code><code><span class="code-snippet_outer">@ConditionalOnClass({ Servlet.<span class="code-snippet__keyword">class</span>, Tomcat.<span class="code-snippet__keyword">class</span>, UpgradeProtocol.<span class="code-snippet__keyword">class</span> })</span></code><code><span class="code-snippet_outer">@ConditionalOnMissingBean(value = ServletWebServerFactory.<span class="code-snippet__keyword">class</span>, search = SearchStrategy.CURRENT)</span></code><code><span class="code-snippet_outer">static <span class="code-snippet__class"><span class="code-snippet__keyword">class</span> <span class="code-snippet__title">EmbeddedTomcat</span> {</span></span></code><code><span class="code-snippet_outer"> @Bean</span></code><code><span class="code-snippet_outer"> TomcatServletWebServerFactory tomcatServletWebServerFactory(</span></code><code><span class="code-snippet_outer"> ObjectProvider<TomcatConnectorCustomizer> connectorCustomizers,</span></code><code><span class="code-snippet_outer"> ObjectProvider<TomcatContextCustomizer> contextCustomizers,</span></code><code><span class="code-snippet_outer"> ObjectProvider<TomcatProtocolHandlerCustomizer<?<span class="code-snippet__meta">>> </span>protocolHandlerCustomizers) {</span></code><code><span class="code-snippet_outer"> TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__regexp">//</span> orderedStream()调用时会去Spring容器中找到TomcatConnectorCustomizer类型的Bean,</span></code><code><span class="code-snippet_outer"> 默认是没有的,程序员可以自己定义</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> factory.getTomcatConnectorCustomizers()</span></code><code><span class="code-snippet_outer"> .addAll(connectorCustomizers.orderedStream().collect(Collectors.toList()));</span></code><code><span class="code-snippet_outer"> factory.getTomcatContextCustomizers()</span></code><code><span class="code-snippet_outer"> .addAll(contextCustomizers.orderedStream().collect(Collectors.toList()));</span></code><code><span class="code-snippet_outer"> factory.getTomcatProtocolHandlerCustomizers()</span></code><code><span class="code-snippet_outer"> .addAll(protocolHandlerCustomizers.orderedStream().collect(Collectors.toList()));</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">return</span> factory;</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer">}</span></code></pre>
</section>
<section data-tools="135编辑器" data-id="7">
<section style="padding-left: 10px;border-left: 5px solid rgb(170, 170, 170);margin: 10px auto;">
<section style="font-size: 13px;letter-spacing: 1px;line-height: 1.75em;color: rgba(102, 102, 102, 0.8);" data-role="list">
<ul class="list-paddingleft-1" style="padding-left: 30px;list-style-position: outside;margin-left: 8px;margin-right: 8px;">
<li style="font-size: 15px;color: rgb(96, 96, 96);letter-spacing: 1px;">
<section style="color: rgb(102, 102, 102);font-size: 14px;letter-spacing: 1.5px;caret-color: red;margin-top: 8px;margin-bottom: 8px;line-height: 1.75em;">
<span style="caret-color: red;font-size: 15px;color: rgb(96, 96, 96);letter-spacing: 1px;">如果用户自己没有定义</span>
<span style="caret-color: red;font-size: 15px;letter-spacing: 1px;color: rgb(255, 76, 0);">ServletWebServerFactory类型</span>
<span style="caret-color: red;font-size: 15px;color: rgb(96, 96, 96);letter-spacing: 1px;">的Bean,那代码中所定义的Bean就会生效。</span>
</section></li>
<li style="font-size: 15px;color: rgb(96, 96, 96);letter-spacing: 1px;">
<section style="color: rgb(102, 102, 102);font-size: 14px;letter-spacing: 1.5px;caret-color: red;margin-top: 8px;margin-bottom: 8px;line-height: 1.75em;">
<span style="caret-color: red;font-size: 15px;color: rgb(96, 96, 96);letter-spacing: 1px;">如果用户自己定义了ServletWebServerFactory类型的Bean,那代码中定义的Bean就不生效 。</span>
</section></li>
</ul>
</section>
</section>
</section>
<section typography="classic">
<p style="min-height: 24px;margin: 24px 8px;line-height: 1.75em;"><span style="letter-spacing: 1px;font-size: 16px;color: rgb(255, 76, 0);">SpringBoot利用该注解来决定到底用用户自己的Bean还是用SpringBoot自定配置的Bean。</span></p>
<p style="min-height: 24px;margin: 24px 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(96, 96, 96);letter-spacing: 1px;">如果先解析自动配置然后再解析程序员定义的,那么就会发现该注解里面的判断是错误的,因为你首先来判断是否成立,是在还没有解析程序员定义的Bean之前,所以就会认为是符合该注解,</span><span style="font-size: 15px;letter-spacing: 1px;color: rgb(255, 76, 0);">实际上只是没有加载程序员定义的,所以必须先去解析程序员定义的,然后最后执行自动配置的</span><span style="font-size: 15px;color: rgb(96, 96, 96);letter-spacing: 1px;">。</span></p>
</section>
</section>
点赞
、在看、转发吧。