<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Spring on I&#39;m company</title>
    <link>http://blog.imcompany.cn/tags/spring/</link>
    <description>Recent content in Spring on I&#39;m company</description>
    <image>
      <title>I&#39;m company</title>
      <url>http://blog.imcompany.cn/%3Clink%20or%20path%20of%20image%20for%20opengraph,%20twitter-cards%3E</url>
      <link>http://blog.imcompany.cn/%3Clink%20or%20path%20of%20image%20for%20opengraph,%20twitter-cards%3E</link>
    </image>
    <generator>Hugo -- 0.154.5</generator>
    <language>en</language>
    <lastBuildDate>Fri, 30 Jan 2026 10:48:47 +0800</lastBuildDate>
    <atom:link href="http://blog.imcompany.cn/tags/spring/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>SpringMVC实践之集成Sentinel限流功能</title>
      <link>http://blog.imcompany.cn/post/spring-webmvc-interceptor-sentinel/</link>
      <pubDate>Fri, 30 Jan 2026 10:48:47 +0800</pubDate>
      <guid>http://blog.imcompany.cn/post/spring-webmvc-interceptor-sentinel/</guid>
      <description>&lt;h2 id=&#34;背景&#34;&gt;背景&lt;/h2&gt;
&lt;p&gt;近期收到线上报警，发现个别新接口在同1s内被请求了接近上百次，对系统的稳定造成了一些影响，近期调研了一下通用的限流框架，打算将Sentinel的限流功能集成进新服务&lt;/p&gt;
&lt;h2 id=&#34;sentinel前置知识&#34;&gt;Sentinel前置知识&lt;/h2&gt;
&lt;p&gt;Sentinel 限流主要涉及以下几方面&lt;/p&gt;
&lt;h3 id=&#34;resource&#34;&gt;Resource&lt;/h3&gt;
&lt;p&gt;限流的资源，资源支持动态加载，核心类为： &lt;code&gt;AbstractDataSource&lt;/code&gt; ，Sentinel 默认提供了市面常见的资源管理服务的实现，也可以自定义实现
&lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/bMQyLZ.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;rule&#34;&gt;Rule&lt;/h3&gt;
&lt;p&gt;对定义的 Resouce 应用的限流规则，基于QPS、响应时间与系统负载。Sentinel 是通过一系列的功能Slot来实现不同的统计/控制功能，对于限流功能对应的就是 &lt;code&gt;FlowSlot&lt;/code&gt;&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/DSNjeo.png&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;&lt;code&gt;FlowSlot&lt;/code&gt; 的功能实现需要依赖前面的 &lt;code&gt;NodeSelectorSlot&lt;/code&gt; 和 &lt;code&gt;ClusterBuilderSlot&lt;/code&gt; 等统计Slot，有了统计信息才可以针对配置进行限流操作，这里面借用一张官方的实现图
&lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/3TQkqg.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;各Slot默认的顺序也可以在代码中找到
&lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/hZyabG.png&#34;&gt;&lt;/p&gt;
&lt;h4 id=&#34;核心处理逻辑&#34;&gt;核心处理逻辑&lt;/h4&gt;
&lt;p&gt;核心逻辑是在执行调用chain的捕获Blockexcption然后执行后续操作&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/514k2Q.png&#34;/&gt; 
&lt;/figure&gt;

&lt;h2 id=&#34;集成步骤&#34;&gt;集成步骤&lt;/h2&gt;
&lt;p&gt;借助SpringMVC中提供的 &lt;code&gt;HandlerInterceptor&lt;/code&gt; 拦截器功能 与 Sentinel 提供的SpringMVC框架集成类库可以方便快速的实现限流功能&lt;/p&gt;
&lt;h3 id=&#34;引入sentinel-springmvc-adapter&#34;&gt;引入Sentinel SpringMVC Adapter&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;com.alibaba.csp&lt;span class=&#34;nt&#34;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;sentinel-spring-webmvc-adapter&lt;span class=&#34;nt&#34;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.8.8&lt;span class=&#34;nt&#34;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;配置sentinelwebinterceptor&#34;&gt;配置SentinelWebInterceptor&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/alibaba/Sentinel/tree/1.8/sentinel-adapter/sentinel-spring-webmvc-adapter&#34;&gt;Sentinel  SpringMVC Adapter&lt;/a&gt;中提供了 &lt;code&gt;SentinelWebInterceptor&lt;/code&gt; 来实现限流功能，这个 Interceptor 支持一些自定义的行为，主要通过 SentinelWebMvcConfig 来实现&lt;/p&gt;
&lt;h4 id=&#34;sentinelwebmvcconfig-常用配置说明&#34;&gt;SentinelWebMvcConfig 常用配置说明&lt;/h4&gt;
&lt;p&gt;SentinelWebMvcConfig 支持以下配置能力&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;urlCleaner&lt;/p&gt;
&lt;figure&gt;
        &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/8I1bRn.png&#34;/&gt; 
    &lt;/figure&gt;

&lt;p&gt;自定义对请求url的处理，比如厂商此次需要通过请求的设备id维度进行限流，对于其它的请求参数都进行忽略，最终可定义效果为: &lt;code&gt;/api/v1/test/ping?did=6308103f1026acf274bbcc1b10001291551xxX&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;httpMethodSpecify&lt;/p&gt;
&lt;p&gt;是否指定特定的Http请求方法，此设置是对资源的请求方法进行了细粒度的配置，默认为false不开启，配置为true后，会在设定好的资源名前加上请求的方法，类似效果:  &lt;code&gt;GET: /api/v1/test/ping?did=6308103f1026acf274bbcc1b10001291551xxX&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;blockExceptionHandler&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/XluwAf.png&#34;&gt;
被Block的请求异常处理器，对Block的请求进行自定义处理，可以设置返回的值，如果未配置则需要服务自己捕获 BlockException，可以通过配置 &lt;code&gt;ExceptionHandler&lt;/code&gt; 进行统一处理&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;originParser&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/njPqHL.png&#34;&gt;
请求来源处理器，针对请求的来源进行处理，在配置资源的规则的可以使用此解析的origin细粒度控制，例如可以解析ip、用户做为请求 origin&lt;/p&gt;</description>
    </item>
    <item>
      <title>Spring学习之@Conditional</title>
      <link>http://blog.imcompany.cn/post/spring-@conditional/</link>
      <pubDate>Wed, 18 Jun 2025 15:00:00 +0800</pubDate>
      <guid>http://blog.imcompany.cn/post/spring-@conditional/</guid>
      <description>&lt;h2 id=&#34;注解说明&#34;&gt;注解说明&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://docs.spring.io/spring-framework/docs/6.2.0/javadoc-api/org/springframework/context/annotation/Conditional.html&#34;&gt;@Conditional&lt;/a&gt; 是 Spring 提供的用于判断是否对 Bean 注入的条件注解(在4.0后版本引入)，只有满足了所有的条件，一个 bean 才会被注册成功并使用。此注解可标注在类上、元注解上、@Bean方法上，通常与 @Configuration 注解配合使用，标识在 @Configuration 注解上的 @Conditional 会影响此配置类的所有 @Bean 注解方法、@Import 注解和@ComponentScan 注解。另需注意 @Conditional 注解不支持继承&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;对于标注在元注解上的样例，可查看 SpringBoot 项目下的 &lt;code&gt;org.springframework.boot.autoconfigure.condition&lt;/code&gt; 包以 ConditionalOn 开头的类&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;注解属性&#34;&gt;注解属性&lt;/h2&gt;
&lt;p&gt;此注解只有一个属性 &lt;code&gt;value&lt;/code&gt; ，返回类型为 Class 数组，它用来配置所有的 &lt;a href=&#34;https://docs.spring.io/spring-framework/docs/6.2.0/javadoc-api/org/springframework/context/annotation/Condition.html&#34;&gt;Condition&lt;/a&gt; 类信息&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/Ndm3ZA.png&#34;/&gt; 
&lt;/figure&gt;

&lt;blockquote&gt;
&lt;p&gt;Condition 是 Spring 提供的一个接口，它提供了 matches 方法来提供判断的依据逻辑，对于其参数 &lt;a href=&#34;https://docs.spring.io/spring-framework/docs/6.2.0/javadoc-api/org/springframework/context/annotation/ConditionContext.html&#34;&gt;ConditionContext&lt;/a&gt; 提供了丰富的上下文信息&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;测试代码&#34;&gt;测试代码&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Configuration&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@ComponentScan&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;basePackages&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;cn.imcompany.bean.condition&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;MyConfiguration&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;@Bean&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;@ConditionalOnDate&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MyBean&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;myBean&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MyBean&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;@Bean&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MyBean2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;myBean2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MyBean2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;@Bean&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;@Conditional&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ConfigPropertyCondition&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MyBean5&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;myBean5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MyBean5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Configuration&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Conditional&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ConfigPropertyCondition&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;MyConfigConfiguration&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;@Bean&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MyBean3&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;myBean3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MyBean3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;@Bean&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MyBean4&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;myBean4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MyBean4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;MyDateCondition&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;implements&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Condition&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;@Override&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;boolean&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;matches&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ConditionContext&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AnnotatedTypeMetadata&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;metadata&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;LocalDateTime&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;now&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;LocalDateTime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;now&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;minute&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;now&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;getMinute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;minute&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 每隔两分钟满足条件&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Retention&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;java&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;lang&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;annotation&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;RetentionPolicy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;RUNTIME&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;java&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;lang&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;annotation&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;ElementType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;TYPE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;java&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;lang&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;annotation&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;ElementType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;METHOD&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Documented&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Conditional&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MyDateCondition&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;@interface&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ConditionalOnDate&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;ConfigPropertyCondition&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;implements&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Condition&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;@Override&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;boolean&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;matches&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ConditionContext&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AnnotatedTypeMetadata&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;metadata&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;equals&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;System&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;getProperty&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;my.config.property&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Main&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;static&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;[]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;System&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;setProperty&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;my.config.property&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AnnotationConfigApplicationContext&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AnnotationConfigApplicationContext&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MyConfiguration&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;beanDefinitionName&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;getBeanDefinitionNames&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;System&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;println&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;beanDefinitionName = &amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;beanDefinitionName&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;源码阅读&#34;&gt;源码阅读&lt;/h2&gt;
&lt;p&gt;对于 Configuration 类条件处理分为两个阶段：&lt;/p&gt;</description>
    </item>
    <item>
      <title>Spring学习之@Bean</title>
      <link>http://blog.imcompany.cn/post/spring-@bean/</link>
      <pubDate>Tue, 17 Jun 2025 17:56:39 +0800</pubDate>
      <guid>http://blog.imcompany.cn/post/spring-@bean/</guid>
      <description>&lt;h2 id=&#34;注解说明&#34;&gt;注解说明&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://docs.spring.io/spring-framework/docs/6.2.0/javadoc-api/org/springframework/context/annotation/Bean.html&#34;&gt;@Bean&lt;/a&gt; 是Spring的一个核心注解，通常与 &lt;a href=&#34;https://blog.imcompany.cn/post/spring-configuration/&#34;&gt;@Configuration&lt;/a&gt; 注解一起使用，用于标记一个方法，方法返回的实体做为Spring管理的一个Bean，通过此注解可以使用JAVA的特性配置对象。默认情况下Bean名字为方法名，也支持通过属性进行配置&lt;/p&gt;
&lt;h2 id=&#34;属性说明&#34;&gt;属性说明&lt;/h2&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/k4Kb1n.png&#34;/&gt; 
&lt;/figure&gt;

&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/xhsjVe.png&#34;/&gt; 
&lt;/figure&gt;

&lt;h3 id=&#34;name&#34;&gt;name&lt;/h3&gt;
&lt;p&gt;自定义Bean的名称，支持配置多个名称，不配置默认为方法名称&lt;/p&gt;
&lt;h3 id=&#34;initmethod&#34;&gt;initMethod&lt;/h3&gt;
&lt;p&gt;配置实例初始化方法，在Bean实例化被调用，默认为空&lt;/p&gt;
&lt;h3 id=&#34;destroymethod&#34;&gt;destroyMethod&lt;/h3&gt;
&lt;p&gt;配置实例销毁方法，默认值为 &lt;code&gt;(inferred)&lt;/code&gt; 即会根据返回的Bean尝试查找识别对象的销毁方法 close 或者 shutdown(限制只查找public无参方法)，如返回一个 &lt;code&gt;BasicDataSource&lt;/code&gt; 实例，会默认查找 &lt;code&gt;close()&lt;/code&gt; 方法进行注册，如果不想Spring进行此操作，需要将此值设置为: &lt;code&gt;destroyMethod=&amp;quot;&amp;quot;&lt;/code&gt; (此配置对 &lt;a href=&#34;https://docs.spring.io/spring-framework/docs/6.2.0/javadoc-api/org/springframework/beans/factory/DisposableBean.html&#34;&gt;DisposableBean&lt;/a&gt; 回调不生效)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;核心逻辑在 DisposableBeanAdapter#inferDestroyMethodsIfNecessary() 方法中&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;与其它注解的关联&#34;&gt;与其它注解的关联&lt;/h2&gt;
&lt;p&gt;@Bean 与XML配置方式中的 &amp;lt;bean&amp;gt; 标签不同，它使用与其它注解组合的方式来实现类型 Scope 或者懒加载的功能，具体可组合注解如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;@Profile&lt;/li&gt;
&lt;li&gt;@Scope&lt;/li&gt;
&lt;li&gt;@Lazy&lt;/li&gt;
&lt;li&gt;@DepednsOn&lt;/li&gt;
&lt;li&gt;@Primary&lt;/li&gt;
&lt;li&gt;@Order&lt;/li&gt;
&lt;li&gt;@Description(给注解bean详细描述，此注解的值会保存在 &lt;code&gt;BeanDefinition&lt;/code&gt; 实例上)&lt;/li&gt;
&lt;li&gt;@Conditional&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;接口默认方法定义bean&#34;&gt;接口默认方法定义Bean&lt;/h2&gt;
&lt;p&gt;Spring 支持在接口中使用默认方法的方式进行bean的定义，方便子类配置类直接复用，示例代码:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;interface&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;BaseConfig&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;@Bean&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;default&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MyBean3&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;myBean3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MyBean3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Configuration&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;AppConfig&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;implements&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;BaseConfig&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;源码阅读&#34;&gt;源码阅读&lt;/h2&gt;
&lt;h3 id=&#34;bean注解配置实例化&#34;&gt;Bean注解配置实例化&lt;/h3&gt;
&lt;p&gt;由于@Bean通常与@Configuration 一起使用，核心逻辑在 refresh 阶段，定位代码发现在 ConfigurationClassParser#doProcessConfigurationClass() 方法进行对 @Bean 标识方法的解析&lt;/p&gt;</description>
    </item>
    <item>
      <title>Spring学习之@Import</title>
      <link>http://blog.imcompany.cn/post/spring-@import/</link>
      <pubDate>Tue, 17 Jun 2025 17:32:55 +0800</pubDate>
      <guid>http://blog.imcompany.cn/post/spring-@import/</guid>
      <description>&lt;h2 id=&#34;注解说明&#34;&gt;注解说明&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://docs.spring.io/spring-framework/docs/6.2.0/javadoc-api/org/springframework/context/annotation/Import.html&#34;&gt;@Import&lt;/a&gt; 注解用于标识多个需要导入的 Component 类，支持导入 @Configuration 类， &lt;a href=&#34;https://docs.spring.io/spring-framework/docs/6.2.0/javadoc-api/org/springframework/context/annotation/ImportSelector.html&#34;&gt;ImportSelector&lt;/a&gt;
与 &lt;a href=&#34;https://docs.spring.io/spring-framework/docs/6.2.0/javadoc-api/org/springframework/context/annotation/ImportBeanDefinitionRegistrar.html&#34;&gt;ImportBeanDefinitionRegistrar&lt;/a&gt; 实现，与 &lt;code&gt;AnnotationConfigApplicationContext.register()&lt;/code&gt; 方法实现的功能类似。此注解常见的实践方式是标注在 EnableXXXX 注解上，用于开启某些功能，在开启功能时就需要通过 @Import 注解来选择导入哪些类的定义&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/Q3KggE.png&#34;/&gt; 
&lt;/figure&gt;

&lt;h2 id=&#34;属性说明&#34;&gt;属性说明&lt;/h2&gt;
&lt;p&gt;此注解只有一个属性 value，返回 &lt;code&gt;Class[]&lt;/code&gt; ，用于标识导入的类&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/jZeILk.png&#34;/&gt; 
&lt;/figure&gt;

&lt;h3 id=&#34;class类型&#34;&gt;Class类型&lt;/h3&gt;
&lt;h4 id=&#34;configuration标识的类&#34;&gt;@Configuration标识的类&lt;/h4&gt;
&lt;p&gt;对于不同功能的配置使用多个 @Configuration 标识，由一个类来 Import 另一个 类的配置，来达到复用的效果&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Configuration&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;MyConfig2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;@Bean&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MyBeanD&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;myBeanD&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MyBeanD&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Configuration&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Import&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MyConfig2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;MyConfig&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;importselector实现类&#34;&gt;ImportSelector实现类&lt;/h4&gt;
&lt;p&gt;所有的 &lt;code&gt;ImportSelector&lt;/code&gt; 实现都需要实现它的 selectImports 方法，来返回要导入的bean类名称集合
&lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/tnwVTo.png&#34;&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;MyImportSelector&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;implements&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ImportSelector&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;@Override&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;[]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;selectImports&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AnnotationMetadata&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;importingClassMetadata&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;[]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MyBeanA&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;getName&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()};&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在 ImportSelector 可以通过Aware或者构造器注入的方式使用 Spring中的容器组件：&lt;/p&gt;</description>
    </item>
    <item>
      <title>Spring学习之@Value</title>
      <link>http://blog.imcompany.cn/post/spring-@value/</link>
      <pubDate>Tue, 10 Jun 2025 16:00:00 +0800</pubDate>
      <guid>http://blog.imcompany.cn/post/spring-@value/</guid>
      <description>&lt;h2 id=&#34;注解说明&#34;&gt;注解说明&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://docs.spring.io/spring-framework/docs/6.2.0/javadoc-api/org/springframework/beans/factory/annotation/Value.html&#34;&gt;@Value&lt;/a&gt; 是Spring提供用于处理属性与表达式注入的注解，可标注在字段、方法或构造器的参数上，并且支持动态解析SpringMVC中的方法参数。支持注入方式：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;直接注入如: @Value(&amp;ldquo;test&amp;rdquo;)&lt;/li&gt;
&lt;li&gt;${my.app.myProp} 属性注入&lt;/li&gt;
&lt;li&gt;#{systemProperties.myProp} SpEL表达式&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;它提供了不同的配置源(属性文件、系统属性)的注入&lt;/p&gt;
&lt;h2 id=&#34;注解属性&#34;&gt;注解属性&lt;/h2&gt;
&lt;p&gt;@Value 注解只有一个属性 &lt;code&gt;value&lt;/code&gt; ，表示要注入的实际值的表达式，支持属性与SpEL表达式两种方式
&lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/RXfWhd.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;测试代码&#34;&gt;测试代码&lt;/h2&gt;
&lt;p&gt;以下测试代码MyController的username的注入值为: tomyli，而不是配置文件中的admin&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Controller&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;MyController&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;@Value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;${USER}&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;@Getter&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;private&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;username&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Configuration&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@ComponentScan&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;basePackages&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;cn.imcompany.bean.autowired&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@PropertySource&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;classpath:application.properties&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;MyConfiguration&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Main&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;static&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;[]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AnnotationConfigApplicationContext&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AnnotationConfigApplicationContext&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MyConfiguration&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MyController&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;myController&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;getBean&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MyController&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;System&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;println&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;myController&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;getUsername&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;());&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// tomyi&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;application-dot-properties配置文件&#34;&gt;application.properties配置文件&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;USER&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;admin
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;源码阅读&#34;&gt;源码阅读&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;@Value&lt;/code&gt; 注解的处理由 &lt;code&gt;AutowiredAnnotationBeanPostProcessor&lt;/code&gt; 类负责，与处理 @Autowired 注解的类为同一个PostProcessor。主要的处理逻辑实现在   &lt;code&gt;DefaultListableBeanFactory#doResolveDependency&lt;/code&gt; 方法，对于 @Value注解的处理主要集中在第2步，解析@Value的操作主要分为3步
&lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/kviZlX.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Spring学习之@Autowireid</title>
      <link>http://blog.imcompany.cn/post/spring-@autowired/</link>
      <pubDate>Fri, 06 Jun 2025 16:00:00 +0800</pubDate>
      <guid>http://blog.imcompany.cn/post/spring-@autowired/</guid>
      <description>&lt;h2 id=&#34;注解说明&#34;&gt;注解说明&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://docs.spring.io/spring-framework/docs/6.2.0/javadoc-api/org/springframework/beans/factory/annotation/Autowired.html&#34;&gt;@Autowired&lt;/a&gt; 是Spring框架的核心注解，用于自动装载构造器、字段、set方法、配置方法上的依赖，它是 &lt;a href=&#34;https://javax-inject.github.io/javax-inject/&#34;&gt;JSR-330 @Inject&lt;/a&gt; 注解的替代，支持配置 &lt;code&gt;依赖是否必须&lt;/code&gt; 选项&lt;/p&gt;
&lt;h2 id=&#34;属性说明&#34;&gt;属性说明&lt;/h2&gt;
&lt;p&gt;此注解只有一个属性 &lt;code&gt;required&lt;/code&gt; ，默认为 true 表示待注入组件必须存在&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/vvxKeV.png&#34;/&gt; 
&lt;/figure&gt;

&lt;h2 id=&#34;注解注入规则说明&#34;&gt;注解注入规则说明&lt;/h2&gt;
&lt;h3 id=&#34;构造器注入&#34;&gt;构造器注入&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;如果一个类声明了多个构造器且没有一个显式标注 @Autowired，则Spring会使用默认的构造方法进行装载&lt;/li&gt;
&lt;li&gt;如果一个类只声明了一个构造器，不管有没有标注 @Autowired 注解它都会被直接使用&lt;/li&gt;
&lt;li&gt;多参数可以配置多个required属性，对于可选注入，可以声明为 Java8 的 &lt;a href=&#34;https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html&#34;&gt;Optional&lt;/a&gt; 类型&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;对于可选注入也可以使用 JSR-305 的 &lt;code&gt;javax.annotation.Nullable&lt;/code&gt; 注解&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;字段注入&#34;&gt;字段注入&lt;/h3&gt;
&lt;p&gt;字段在构造器之后，配置方法注入之前进行自动注入&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;字段注入支持组件自引用(self references)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;方法注入&#34;&gt;方法注入&lt;/h3&gt;
&lt;p&gt;方法注入不限制方法名与参数个数，所有参数会被Spring进行匹配注入&lt;/p&gt;
&lt;h3 id=&#34;参数注入&#34;&gt;参数注入&lt;/h3&gt;
&lt;p&gt;目前只在 &lt;a href=&#34;https://docs.spring.io/spring-framework/reference/testing.html&#34;&gt;spring-test&lt;/a&gt; 模块中有效，其它地方使用会被忽略&lt;/p&gt;
&lt;h3 id=&#34;数组-集合注入&#34;&gt;数组/集合注入&lt;/h3&gt;
&lt;p&gt;Spring通过匹配数组/集合的值进行注入，Map的key必须为String类型，支持集合中元素的Order配置&lt;/p&gt;
&lt;h3 id=&#34;不支持-beanpostprocessor-或者-beanfactorypostprocessor&#34;&gt;不支持 BeanPostProcessor 或者 BeanFactoryPostProcessor&lt;/h3&gt;
&lt;p&gt;因为真实的注入动作发生在 &lt;code&gt;BeanPostProcessor&lt;/code&gt; 阶段，所以不能在 &lt;code&gt;BeanPostProcessor&lt;/code&gt; 或者 &lt;code&gt;BeanFactoryPostProcessor&lt;/code&gt; 中使用此注解&lt;/p&gt;
&lt;h2 id=&#34;源码阅读&#34;&gt;源码阅读&lt;/h2&gt;
&lt;p&gt;在Spring中，处理 @Autowired 注解对应的类为 &lt;a href=&#34;https://docs.spring.io/spring-framework/docs/6.2.0/javadoc-api/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.html&#34;&gt;AutowiredAnnotationBeanPostProcessor&lt;/a&gt; ，又是一个Bean后置处理器&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/3DVo64.png&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;对于此类，需要关注其实现的两个接口类 &lt;code&gt;MergedBeanDefinitionPostProcessor&lt;/code&gt; (运行时合并Bean的定义回调接口)和 &lt;code&gt;InstantiationAwareBeanPostProcessor&lt;/code&gt; (在Bean实例化前后进行处理后置处理器)&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;MergedBeanDefinitionPostProcessor 主要是为了在真正bean实例化前准备缓存的bean元数据&lt;/li&gt;
&lt;li&gt;InstantiationAwareBeanPostProcessor Bean实例化回调接口，通常用于为bean创建代理&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;测试代码&#34;&gt;测试代码&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Service&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;MyService&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Controller&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;MyController&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;@Autowired&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MyService&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;myService&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;showService&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;System&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;println&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;myService = &amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;myService&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Configuration&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@ComponentScan&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;basePackages&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;cn.imcompany.bean.autowired&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;MyConfiguration&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Main&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;static&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;[]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AnnotationConfigApplicationContext&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AnnotationConfigApplicationContext&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MyConfiguration&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MyController&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;myController&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;getBean&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MyController&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;myController&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;showService&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;元数据收集&#34;&gt;元数据收集&lt;/h3&gt;
&lt;p&gt;调用栈信息如下：&lt;/p&gt;</description>
    </item>
    <item>
      <title>Spring学习之@CompnentScan</title>
      <link>http://blog.imcompany.cn/post/spring-componentscan/</link>
      <pubDate>Thu, 15 May 2025 16:29:33 +0800</pubDate>
      <guid>http://blog.imcompany.cn/post/spring-componentscan/</guid>
      <description>&lt;h2 id=&#34;注解说明&#34;&gt;注解说明&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://docs.spring.io/spring-framework/docs/6.2.0/javadoc-api/org/springframework/context/annotation/ComponentScan.html&#34;&gt;@ComponentScan&lt;/a&gt; 注解是Spring 提供的对组件进行扫描的注解指令，通常与 &lt;a href=&#34;https://blog.imcompany.cn/post/spring-configuration/&#34;&gt;@Configuration&lt;/a&gt; 注解一起使用，支持在类上重复标注&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/1Gfqcy.png&#34;/&gt; 
&lt;/figure&gt;

&lt;h2 id=&#34;注解能做什么&#34;&gt;注解能做什么？&lt;/h2&gt;
&lt;p&gt;此注解支持以下重要特性:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;自定义扫描的包范围&lt;/li&gt;
&lt;li&gt;配置包含扫描组件的过滤器&lt;/li&gt;
&lt;li&gt;配置排除组件的过滤器&lt;/li&gt;
&lt;li&gt;是否使用默认过滤器&lt;/li&gt;
&lt;li&gt;是否配置懒加载&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;源码分析&#34;&gt;源码分析&lt;/h2&gt;
&lt;p&gt;由于此注解通常与 @Configuration 注解一起使用，其解析的主要逻辑都是在 refresh 阶段的 invokeBeanFactoryPostProcessors 方法中，最终会定位到   &lt;code&gt;ConfigurationClassParser#doProcessConfigurationClass()&lt;/code&gt; 方法中，在方法中可以看到对 ComponentScan 注解的操作逻辑了&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/nLgM3W.png&#34;/&gt; 
&lt;/figure&gt;

&lt;h3 id=&#34;对注解属性的解析&#34;&gt;对注解属性的解析&lt;/h3&gt;
&lt;p&gt;所有对属性的解析都在 &lt;code&gt;ComponentScanAnnotationParser#parse()&lt;/code&gt; 方法中进行，此方法中会创建一个 &lt;a href=&#34;https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/ClassPathBeanDefinitionScanner.html&#34;&gt;ClassPathBeanDefinitionScanner&lt;/a&gt; 实例scanner，此实例初始化过程中会对默认的Filter进行加载&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/vRkGfu.png&#34;/&gt; 
&lt;/figure&gt;

&lt;blockquote&gt;
&lt;p&gt;处理默认Filter主要是 &lt;a href=&#34;https://www.ibm.com/docs/en/wasdtfe?topic=reference-jax-ws-common-annotations-jsr-250&#34;&gt;JSR-250&lt;/a&gt; 与 &lt;a href=&#34;https://jcp.org/en/jsr/detail?id=330&#34;&gt;JSR-330&lt;/a&gt; API 增加的注解&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;然后会把配置的 &lt;code&gt;includeFilter&lt;/code&gt; 和 &lt;code&gt;excludeFilter&lt;/code&gt; 设置到 scanner 中，接着会对 &lt;code&gt;basePackage&lt;/code&gt; 扫描包属性进行解析配置，如果配置了就添加，没有配置，默认就使用 &lt;code&gt;@ComponentScan&lt;/code&gt; 注解标注类所在的包路径。解析完注解属性后，就开始了真正的扫描操作&lt;/p&gt;
&lt;h3 id=&#34;扫描操作&#34;&gt;扫描操作&lt;/h3&gt;
&lt;p&gt;扫描操作由  &lt;code&gt;ClassPathBeanDefinitionScanner#doScan()&lt;/code&gt; 方法进行处理，此方法会调用 &lt;code&gt;findCandidateComponents()&lt;/code&gt; 方法在给定的包下查找符合条件的组件，查找的任务由 &lt;code&gt;scanCandidateComponents()&lt;/code&gt; 进行，该方法调用 &lt;code&gt;isCandidateComponent()&lt;/code&gt; 方法，根据解析的includeFilter和excludeFilter 来选择满足条件的组件&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/V9WgPz.png&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;这样扫描到所有满足条件的Bean后，会接着对这些Bean进行parse操作，直到注解再无其它依赖&lt;/p&gt;
&lt;h3 id=&#34;注册bean&#34;&gt;注册Bean&lt;/h3&gt;
&lt;p&gt;扫描完所有Bean后，会调用 &lt;code&gt;checkCandidate()&lt;/code&gt; 方法进行检查，检查当前要注册的Bean是否与已经注册过的Bean的定义是否兼容，如果冲突会报 &lt;code&gt;ConflictingBeanDefinitionException&lt;/code&gt; 。检查没问题后，会调用 &lt;code&gt;registerBeanDefinition()&lt;/code&gt; 方法对Bean进行注册，这个过程就涉及到Spring其它的生命周期了（这个后续专门学习总结），对于@ComponentScan 组件来说已经完成了它的使命&lt;/p&gt;
&lt;h2 id=&#34;总结&#34;&gt;总结&lt;/h2&gt;
&lt;p&gt;最后以注解解析过程中的涉及的核心类做一下总结&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/At29IK.png&#34;/&gt; 
&lt;/figure&gt;

&lt;h2 id=&#34;常见问题&#34;&gt;常见问题&lt;/h2&gt;
&lt;h3 id=&#34;调整包结构后一些-bean配置扫描不到了&#34;&gt;调整包结构后一些@Bean配置扫描不到了&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;调用启动类的包路径为最外层，这样可以扫描当前包及子包的配置&lt;/li&gt;
&lt;li&gt;默认只扫描当前标注注解的包，可以通过配置 &lt;code&gt;basePackage&lt;/code&gt; 属性指定扫描路径，配置后默认的扫描路径就不生效了&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;如何将未配置spring相关组件注解的bean纳入spring管理&#34;&gt;如何将未配置Spring相关组件注解的Bean纳入Spring管理?&lt;/h3&gt;
&lt;p&gt;可以通过配置 ComponentScan的includeFilter 来实现&lt;/p&gt;</description>
    </item>
    <item>
      <title>Spring学习之@Configuration</title>
      <link>http://blog.imcompany.cn/post/spring-configuration/</link>
      <pubDate>Fri, 09 May 2025 11:40:11 +0800</pubDate>
      <guid>http://blog.imcompany.cn/post/spring-configuration/</guid>
      <description>&lt;h2 id=&#34;configuration是什么&#34;&gt;@Configuration是什么？&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://docs.spring.io/spring-framework/docs/6.2.0/javadoc-api/org/springframework/context/annotation/Configuration.html&#34;&gt;@Configuration&lt;/a&gt; 是 Spring提供的一个用于配置与声明Bean与相应Bean之间依赖的注解，根据文档描述，此注解通常由 &lt;a href=&#34;https://docs.spring.io/spring-framework/docs/6.2.0/javadoc-api/org/springframework/web/context/support/AnnotationConfigWebApplicationContext.html&#34;&gt;AnnotationConfigApplicationContext&lt;/a&gt; 上下文进行启动加载&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/PRtMuy.png&#34;/&gt; 
&lt;/figure&gt;

&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/fYfwMj.png&#34;/&gt; 
&lt;/figure&gt;

&lt;h2 id=&#34;configuration能做什么&#34;&gt;@Configuration能做什么？&lt;/h2&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/5R7RVf.png&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;先看一下此注解的声明，在此注解上标识了 &lt;a href=&#34;https://docs.spring.io/spring-framework/docs/6.2.0/javadoc-api/org/springframework/stereotype/Component.html&#34;&gt;@Component&lt;/a&gt; ，则证明此注解是一个 Component，拥有 &lt;code&gt;@Component&lt;/code&gt; 注解的基础能力(可以被Spring容器自动扫描与加载)&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/61UMNj.png&#34;&gt;
&lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/XHjgyf.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;上图标识了注解常用的配置方式，分类为以下几种&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;属性资源导入&lt;/li&gt;
&lt;li&gt;引入其它配置类的配置&lt;/li&gt;
&lt;li&gt;Value注入&lt;/li&gt;
&lt;li&gt;Spring容器组件注入&lt;/li&gt;
&lt;li&gt;支持Profile配置&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;注解属性&#34;&gt;注解属性&lt;/h2&gt;
&lt;p&gt;在Spring5.x版本中，只支持两个属性配置&lt;/p&gt;
&lt;h3 id=&#34;value&#34;&gt;value&lt;/h3&gt;
&lt;p&gt;配置注解的名称&lt;/p&gt;
&lt;h3 id=&#34;proxybeanmethods&#34;&gt;proxyBeanMethods&lt;/h3&gt;
&lt;p&gt;是否代理增强(基于CGLIB)标识 @Bean 的方法，默认为true，保证声明的bean是单例共享的，而不是每一次通过方法调用都生成一个新的&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/2hAi0n.png&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;此属性的两个值被定义为两种模式&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;full 模式(值为true)&lt;/li&gt;
&lt;li&gt;lite 模式(值为false)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;源码分析&#34;&gt;源码分析&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;@Configuration&lt;/code&gt; 注解的解析类为 &lt;a href=&#34;https://docs.spring.io/spring-framework/docs/6.2.0/javadoc-api/org/springframework/context/annotation/ConfigurationClassPostProcessor.html&#34;&gt;ConfigurationClassPostProcessor&lt;/a&gt; ，本次主要关注从  &lt;code&gt;AnnotationConfigApplicationContext&lt;/code&gt; 启动后的整个处理过程， &lt;code&gt;AnnotationConfigApplicationContext&lt;/code&gt; 启动分为三个阶段&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/CjzEJ4.png&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;先上一张三个阶段的涉及的主要类与调用关系图
&lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/khv7Ac.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;初始化&#34;&gt;初始化&lt;/h3&gt;
&lt;h4 id=&#34;初始化reader&#34;&gt;初始化reader&lt;/h4&gt;
&lt;p&gt;此过程会实例化 &lt;code&gt;AnnotatedBeanDefinitionReader&lt;/code&gt; 类，此类在实例化时会调用 &lt;code&gt;AnnotationConfigUtils.registerAnnotationConfigProcessors&lt;/code&gt; 来注册解析配置的Processor，如果registry中没有包含 &lt;code&gt;ConfigurationClassPostProcessor&lt;/code&gt; 类的定义，则会新new一个 &lt;code&gt;ConfigurationClassPostProcessor&lt;/code&gt; 的Bean定义类&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/Hc0pp8.png&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;整体调用链路如下：&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/mkddrx.png&#34;/&gt; 
&lt;/figure&gt;

&lt;h4 id=&#34;初始化scanner&#34;&gt;初始化scanner&lt;/h4&gt;
&lt;p&gt;此过程会实例化Bean定义扫描器 &lt;code&gt;ClassPathBeanDefinitionScanner&lt;/code&gt; , 在此过程中主要会设置 Environment 和 ResourceLoader 相关信息&lt;/p&gt;
&lt;h3 id=&#34;注册&#34;&gt;注册&lt;/h3&gt;
&lt;p&gt;注册阶段主要是对标注了 &lt;code&gt;@Configuration&lt;/code&gt; 类(MyConfig)进行注册，以便Spring可以正常识别，主要逻辑在 &lt;code&gt;AnnotatedBeanDefinitionReader#doRegisterBean&lt;/code&gt; 中，此方法会调用 &lt;code&gt;BeanDefinitionReaderUtils.registerBeanDefinition&lt;/code&gt; 对此Bean进行注册&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/xbi8aV.png&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/XNcLXU.png&#34;&gt;
至此， &lt;code&gt;@Configuration&lt;/code&gt; 类信息就注册到了 Spring 容器中&lt;/p&gt;</description>
    </item>
    <item>
      <title>SpringMVC实践之集成Sentinel限流功能</title>
      <link>http://blog.imcompany.cn/post/spring-webmvc-interceptor/</link>
      <pubDate>Fri, 25 Apr 2025 17:53:54 +0800</pubDate>
      <guid>http://blog.imcompany.cn/post/spring-webmvc-interceptor/</guid>
      <description>&lt;h2 id=&#34;背景&#34;&gt;背景&lt;/h2&gt;
&lt;p&gt;近期收到线上报警，发现个别新接口在同1s内被请求了接近上百次，对系统的稳定造成了一些影响，近期调研了一下通用的限流框架，打算将Sentinel的限流功能集成进新服务&lt;/p&gt;
&lt;h2 id=&#34;sentinel前置知识&#34;&gt;Sentinel前置知识&lt;/h2&gt;
&lt;p&gt;Sentinel 限流主要涉及以下几方面&lt;/p&gt;
&lt;h3 id=&#34;resource&#34;&gt;Resource&lt;/h3&gt;
&lt;p&gt;限流的资源，资源支持动态加载，核心类为： &lt;code&gt;AbstractDataSource&lt;/code&gt; ，Sentinel 默认提供了市面常见的资源管理服务的实现，也可以自定义实现
&lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/bMQyLZ.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;rule&#34;&gt;Rule&lt;/h3&gt;
&lt;p&gt;对定义的 Resouce 应用的限流规则，基于QPS、响应时间与系统负载。Sentinel 是通过一系列的功能Slot来实现不同的统计/控制功能，对于限流功能对应的就是 &lt;code&gt;FlowSlot&lt;/code&gt;&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/DSNjeo.png&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;&lt;code&gt;FlowSlot&lt;/code&gt; 的功能实现需要依赖前面的 &lt;code&gt;NodeSelectorSlot&lt;/code&gt; 和 &lt;code&gt;ClusterBuilderSlot&lt;/code&gt; 等统计Slot，有了统计信息才可以针对配置进行限流操作，这里面借用一张官方的实现图
&lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/3TQkqg.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;各Slot默认的顺序也可以在代码中找到
&lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/hZyabG.png&#34;&gt;&lt;/p&gt;
&lt;h4 id=&#34;核心处理逻辑&#34;&gt;核心处理逻辑&lt;/h4&gt;
&lt;p&gt;核心逻辑是在执行调用chain的捕获Blockexcption然后执行后续操作&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/514k2Q.png&#34;/&gt; 
&lt;/figure&gt;

&lt;h2 id=&#34;集成步骤&#34;&gt;集成步骤&lt;/h2&gt;
&lt;p&gt;借助SpringMVC中提供的 &lt;code&gt;HandlerInterceptor&lt;/code&gt; 拦截器功能 与 Sentinel 提供的SpringMVC框架集成类库可以方便快速的实现限流功能&lt;/p&gt;
&lt;h3 id=&#34;引入sentinel-springmvc-adapter&#34;&gt;引入Sentinel SpringMVC Adapter&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;com.alibaba.csp&lt;span class=&#34;nt&#34;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;sentinel-spring-webmvc-adapter&lt;span class=&#34;nt&#34;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.8.8&lt;span class=&#34;nt&#34;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;配置sentinelwebinterceptor&#34;&gt;配置SentinelWebInterceptor&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/alibaba/Sentinel/tree/1.8/sentinel-adapter/sentinel-spring-webmvc-adapter&#34;&gt;Sentinel  SpringMVC Adapter&lt;/a&gt;中提供了 &lt;code&gt;SentinelWebInterceptor&lt;/code&gt; 来实现限流功能，这个 Interceptor 支持一些自定义的行为，主要通过 SentinelWebMvcConfig 来实现&lt;/p&gt;
&lt;h4 id=&#34;sentinelwebmvcconfig-常用配置说明&#34;&gt;SentinelWebMvcConfig 常用配置说明&lt;/h4&gt;
&lt;p&gt;SentinelWebMvcConfig 支持以下配置能力&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;urlCleaner&lt;/p&gt;
&lt;figure&gt;
        &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/8I1bRn.png&#34;/&gt; 
    &lt;/figure&gt;

&lt;p&gt;自定义对请求url的处理，比如厂商此次需要通过请求的设备id维度进行限流，对于其它的请求参数都进行忽略，最终可定义效果为: &lt;code&gt;/api/v1/test/ping?did=6308103f1026acf274bbcc1b10001291551xxX&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;httpMethodSpecify&lt;/p&gt;
&lt;p&gt;是否指定特定的Http请求方法，此设置是对资源的请求方法进行了细粒度的配置，默认为false不开启，配置为true后，会在设定好的资源名前加上请求的方法，类似效果:  &lt;code&gt;GET: /api/v1/test/ping?did=6308103f1026acf274bbcc1b10001291551xxX&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;blockExceptionHandler&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/XluwAf.png&#34;&gt;
被Block的请求异常处理器，对Block的请求进行自定义处理，可以设置返回的值，如果未配置则需要服务自己捕获 BlockException，可以通过配置 &lt;code&gt;ExceptionHandler&lt;/code&gt; 进行统一处理&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;originParser&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/njPqHL.png&#34;&gt;
请求来源处理器，针对请求的来源进行处理，在配置资源的规则的可以使用此解析的origin细粒度控制，例如可以解析ip、用户做为请求 origin&lt;/p&gt;</description>
    </item>
    <item>
      <title>SpringMVC学习之HandlerMapping</title>
      <link>http://blog.imcompany.cn/post/spring-webmvc-handler/</link>
      <pubDate>Fri, 18 Apr 2025 11:27:45 +0800</pubDate>
      <guid>http://blog.imcompany.cn/post/spring-webmvc-handler/</guid>
      <description>&lt;h2 id=&#34;起因&#34;&gt;起因&lt;/h2&gt;
&lt;p&gt;新服务在处理不存在的url请求时，上报日志报错，具体错误信息：
&lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/6yGXgJ.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;根据报错信息找到相关代码
&lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/3q8RWR.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;代码处做了对参数hanler的强制转换，但是真正传入的参数类型为 ResourceHttpRequestHandler 导致转换失败而报错，梳理一下，handler是在 自定义的日志Interceptor 的afterCompletion方法中由框架传入的
&lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/h8fQR5.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;resourcehttprequesthandler-是什么&#34;&gt;ResourceHttpRequestHandler 是什么?&lt;/h2&gt;
&lt;p&gt;查阅类文档，ResourceHttpRequestHandler是SpringMVC提供的处理静态资源的Handler，比如常见的js或者css文件。在当前前后端分离的分工下，对于REST服务开发，不会再使用这种方式提供对静态资源的访问，为什么请求了一个不存在的url，会使用静态资源的Hanlder来处理?&lt;/p&gt;
&lt;h2 id=&#34;springmvc提供了哪些handlermapping&#34;&gt;SpringMVC提供了哪些HandlerMapping?&lt;/h2&gt;
&lt;p&gt;SpringMVC提供的HanlderMapping位于 org.springframework.web.servlet.handler 包下，主要包含&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Mapping&lt;/th&gt;
          &lt;th&gt;Desc&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;RequestMappingHandlerMapping&lt;/td&gt;
          &lt;td&gt;处理@RequestMapping 注解映射关系&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;SimpleUrlHandlerMapping&lt;/td&gt;
          &lt;td&gt;使用URL模式匹配映射关系&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;BeanNameUrlHandlerMapping&lt;/td&gt;
          &lt;td&gt;基于Bean名匹配映射关系&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/CeRZGp.png&#34;/&gt; 
&lt;/figure&gt;

&lt;h3 id=&#34;springmvc-路径映射流程回顾&#34;&gt;SpringMVC 路径映射流程回顾&lt;/h3&gt;
&lt;p&gt;回顾一下SpringMVC的路径映射流程，通常的url请求的编码方式为:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@RequestMapping&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;/ping&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Response&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;ping&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;success&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;pong&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;标识了 @RequestMapping 注解的方法会被 SpringMVC 框架的 RequestMappingHandlerMapping 类在启动时进行扫描并根据映射信息来创建 RequestMappingInfo(RequestMappingInfo 类维护请求的映射信息)，扫描后的所有Mapping信息在 MappingRegistry(AbstractHandlerMethodMapping内部类) 类进行维护&lt;/p&gt;
&lt;figure&gt;&lt;a href=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/D0VzNH.png&#34;&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/D0VzNH.png&#34;/&gt; &lt;/a&gt;
&lt;/figure&gt;

&lt;h2 id=&#34;springmvc如何处理request与handlermethod的映射关系&#34;&gt;SpringMVC如何处理request与HandlerMethod的映射关系&lt;/h2&gt;
&lt;p&gt;AbstractHandlerMethodMapping的getHandler 方法用来通过给定的request来找到一个合适的handler进行处理
&lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/RobS4l.png&#34;&gt;
&lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/RqkBp1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;getHandler会先调用抽象方法 getHandlerInternal 由子类实现查找逻辑，如果找不到，则查找默认配置的Hanlder，默认Hanlder找不到则返回null&lt;/p&gt;
&lt;h2 id=&#34;springmvc默认使用了哪些handlermapping&#34;&gt;SpringMVC默认使用了哪些HandlerMapping&lt;/h2&gt;
&lt;p&gt;如何查询Handler是在 DispacherServlet的getHandler方法操作的，它会在所有的handlerMappings(有序handlerMapping)中查找出一个可用的handler进行request的处理
&lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/fR6ezN.png&#34;&gt;&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/kYtDXf.png&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;如图可知会在7个handlerMapping中依次进行查询，这些handlerMapping是在 &lt;code&gt;DispatcherServlet#initHandlerMappings()&lt;/code&gt;  设置的&lt;/p&gt;
&lt;h2 id=&#34;定位到问题原因&#34;&gt;定位到问题原因&lt;/h2&gt;
&lt;p&gt;跟踪请求代码发现对于不存在的url会在 SimpleUrlHanlderMapping中找到可用的handler，因为最终请求url匹配上了 /**，而 /** 模式对应的handler就是 ResourceHttpRequestHandler，此时getHandler的结果就是ResourceHttpRequestHandler 了，但是在上报时使用的是 HandlerMethod，执行到此时报了转换异常&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/FNSevN.png&#34;/&gt; 
&lt;/figure&gt;

&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/pBVyIz.png&#34;/&gt; 
&lt;/figure&gt;

&lt;h2 id=&#34;webmvcautoconfiguration中的sourcehandler在哪注册的&#34;&gt;WebMvcAutoConfiguration中的SourceHandler在哪注册的？&lt;/h2&gt;
&lt;p&gt;在启用MVC功能时，会增加注解 @EnableWebMvc，而对应的MVC配置类为 WebMvcConfigurationSupport，在这个类中进行SourceHandler的注册。跟踪代码发现两个ResourceHandler是在 WebMvcAutoConfigurationAdapter中添加的&lt;/p&gt;</description>
    </item>
    <item>
      <title>SpringMVC学习之Exception处理</title>
      <link>http://blog.imcompany.cn/post/spring-webmvc-exception/</link>
      <pubDate>Mon, 14 Apr 2025 11:04:00 +0800</pubDate>
      <guid>http://blog.imcompany.cn/post/spring-webmvc-exception/</guid>
      <description>&lt;h2 id=&#34;背景&#34;&gt;背景&lt;/h2&gt;
&lt;p&gt;开发过程中，会出现很多异常情况，比如RPC调用异常、请求参数异常，SpringMVC是如何处理异常信息的?&lt;/p&gt;
&lt;h2 id=&#34;spring处理异常的方式&#34;&gt;Spring处理异常的方式&lt;/h2&gt;
&lt;p&gt;Spring采用了全局的异常捕获统一处理的方式，虽然JAVA的异常机制一直有争议，但是Spring还是选择基于实际开发需要使用抛异常后捕获统一处理的方式&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/yZjYzc.png&#34;/&gt; 
&lt;/figure&gt;

&lt;h2 id=&#34;handlerexceptionresolver登场&#34;&gt;HandlerExceptionResolver登场&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;HandlerExceptionResolver&lt;/code&gt; 是SpringMVC提供的解析Handler调用过程抛出异常的解析器，只提供了一个解析异常的方法 &lt;code&gt;resovleException&lt;/code&gt;&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/VTJMf6.png&#34;/&gt; 
&lt;/figure&gt;

&lt;h3 id=&#34;spring提供了哪些exceptionresolver&#34;&gt;Spring提供了哪些ExceptionResolver?&lt;/h3&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/ndAxqw.png&#34;/&gt; 
&lt;/figure&gt;

&lt;h4 id=&#34;经典的interface-abstract方式的实现类&#34;&gt;经典的Interface-Abstract方式的实现类&lt;/h4&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Resolver&lt;/th&gt;
          &lt;th&gt;Desc&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;SimpleMappingExceptionResolver&lt;/td&gt;
          &lt;td&gt;提供exception class name到view的映射&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;DefaultHandlerExceptionResolver&lt;/td&gt;
          &lt;td&gt;默认Resolver实现，用于解析标准的SpringMVC异常并转换成对应的Http状态码&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;ResponseStatusExceptionResolver&lt;/td&gt;
          &lt;td&gt;基于 @ResponseStatus 注解来映射异常与Http状态码&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;ExceptionHandlerExceptionResolver&lt;/td&gt;
          &lt;td&gt;基于 @ExceptionHalder 注解来解析处理异常信息&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&#34;直接实现handlerexceptionresolver的类&#34;&gt;直接实现HandlerExceptionResolver的类&lt;/h4&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Resolver&lt;/th&gt;
          &lt;th&gt;Desc&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;DefaultErrorAttributes&lt;/td&gt;
          &lt;td&gt;默认错误属性实现&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;HandlerExceptionResolverComposite&lt;/td&gt;
          &lt;td&gt;代理其它Resolver集合的ExceptionResolver&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code&gt;HandlerExceptionResolverComposite&lt;/code&gt; 中包含了一个解析列表，可以判断是会排序后顺序调用，以找到第一个可以处理的Resolver&lt;/p&gt;
&lt;h2 id=&#34;具体异常处理流程&#34;&gt;具体异常处理流程&lt;/h2&gt;
&lt;p&gt;异常处理的核心逻辑都在 &lt;code&gt;processHandlerException&lt;/code&gt; 方法中，Spring处理完请求后，如果有异常抛出，则会把异常信息传给 &lt;code&gt;processHandlerException&lt;/code&gt; 方法， &lt;code&gt;processHandlerException&lt;/code&gt; 遍历持有的 handlerExceptionResolvers 进行对异常的解析，如果解析成功则直接返回对应的 ModelAndView(此返回与正常的handler处理返回保持了一致)&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/oQdSdj.png&#34;/&gt; 
&lt;/figure&gt;

&lt;h3 id=&#34;handlerexceptionresolvers-有哪些&#34;&gt;handlerExceptionResolvers 有哪些？&lt;/h3&gt;
&lt;p&gt;在 SpringMVC启动时会调用 &lt;code&gt;initHandlerExceptionResolvers&lt;/code&gt; 方法来查找所有可用的 handlerExceptionResolver 并保存到 &lt;code&gt;handlerExceptionResolvers&lt;/code&gt; 变量中。SpringMVC配置了两个 resolver 来提供异常解析&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/ZkaEcp.png&#34;/&gt; 
&lt;/figure&gt;

&lt;h4 id=&#34;errorattributes&#34;&gt;errorAttributes&lt;/h4&gt;
&lt;p&gt;此Resolver是在 &lt;code&gt;ErrorMvcAutoConfiguration&lt;/code&gt; 进行实例化的
&lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/lkrPBk.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;此实现的 resolverExcption 方法逻辑简单，直接返回了null，不是关注重点&lt;/p&gt;
&lt;h4 id=&#34;handlerexceptionresolver&#34;&gt;handlerExceptionResolver&lt;/h4&gt;
&lt;p&gt;此Resolver真正的实现类为 &lt;code&gt;HandlerExceptionResolverComposite&lt;/code&gt; ，也就是持有多个ExceptionResolver列表的 Resolver，它是在 &lt;code&gt;WebMvcConfigurationSupport&lt;/code&gt; 实例化的&lt;/p&gt;</description>
    </item>
    <item>
      <title>SpringMVC统一配置接口WebMvcConfigurer功能</title>
      <link>http://blog.imcompany.cn/post/spring-webmvcconfigurer/</link>
      <pubDate>Fri, 28 Mar 2025 18:18:10 +0800</pubDate>
      <guid>http://blog.imcompany.cn/post/spring-webmvcconfigurer/</guid>
      <description>&lt;h2 id=&#34;接口说明&#34;&gt;接口说明&lt;/h2&gt;
&lt;p&gt;WebMvcConfigurer是Spring提供的统一配置接口，用于自定义Spring MVC的配置，全局更改服务的行为，提供的可配置项：
&lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/NGXzbc.png&#34;&gt;&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;方法名称&lt;/th&gt;
          &lt;th&gt;参数&lt;/th&gt;
          &lt;th&gt;用途&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;addArgumentResolvers(List&amp;lt;HandlerMethodArgumentResolver&amp;gt; argumentResolvers)&lt;/td&gt;
          &lt;td&gt;List&amp;lt;HandlerMethodArgumentResolver&amp;gt; argumentResolvers&lt;/td&gt;
          &lt;td&gt;添加自定义的 HandlerMethodArgumentResolver 用于解析方法参数。&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;addCorsMappings(CorsRegistry registry)&lt;/td&gt;
          &lt;td&gt;CorsRegistry registry&lt;/td&gt;
          &lt;td&gt;配置跨域资源共享 (CORS)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;addFormatters(FormatterRegistry registry)&lt;/td&gt;
          &lt;td&gt;FormatterRegistry registry&lt;/td&gt;
          &lt;td&gt;添加自定义的格式化程序和转换器&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;addInterceptors(InterceptorRegistry registry)&lt;/td&gt;
          &lt;td&gt;InterceptorRegistry registry&lt;/td&gt;
          &lt;td&gt;添加自定义的拦截器&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;addRequestMappings(RequestMappingInfo customization, Class&amp;lt;Controller&amp;gt; controllerClass)&lt;/td&gt;
          &lt;td&gt;RequestMappingInfo customization, Class&amp;lt;Controller&amp;gt; controllerClass&lt;/td&gt;
          &lt;td&gt;关联自定义请求映射到具控制器类&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;addResourceHandlers(ResourceHandlerRegistry registry)&lt;/td&gt;
          &lt;td&gt;ResourceHandlerRegistry registry&lt;/td&gt;
          &lt;td&gt;配置资源处理，如静态资源路径&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;addReturnValueHandlers(List&amp;lt;HandlerMethodReturnValueHandler&amp;gt; returnValueHandlers)&lt;/td&gt;
          &lt;td&gt;List&amp;lt;HandlerMethodReturnValueHandler&amp;gt; returnValueHandlers&lt;/td&gt;
          &lt;td&gt;添加自定义的 HandlerMethodReturnValueHandler 用于处理方法返回值&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;addViewControllers(ViewControllerRegistry registry)&lt;/td&gt;
          &lt;td&gt;ViewControllerRegistry registry&lt;/td&gt;
          &lt;td&gt;注册视图控制器&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;configureAsyncSupport(AsyncSupportConfigurer configurer)&lt;/td&gt;
          &lt;td&gt;AsyncSupportConfigurer configurer&lt;/td&gt;
          &lt;td&gt;配置异步支持&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;configureContentNegotiation(ContentNegotiationConfigurer configurer)&lt;/td&gt;
          &lt;td&gt;ContentNegotiationConfigurer configurer&lt;/td&gt;
          &lt;td&gt;配置内容协商策略&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer)&lt;/td&gt;
          &lt;td&gt;DefaultServletHandlerConfigurer configurer&lt;/td&gt;
          &lt;td&gt;启用默认 Servlet 处理&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;configureHandlerExceptionResolvers(List&amp;lt;HandlerExceptionResolver&amp;gt; exceptionResolvers)&lt;/td&gt;
          &lt;td&gt;List&amp;lt;HandlerExceptionResolver&amp;gt; exceptionResolvers&lt;/td&gt;
          &lt;td&gt;配置异常处理程序&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;configureMessageConverters(List&amp;lt;HttpMessageConverter&amp;lt;?&amp;gt;&amp;gt; converters)&lt;/td&gt;
          &lt;td&gt;List&amp;lt;HttpMessageConverter&amp;lt;?&amp;gt;&amp;gt; converters&lt;/td&gt;
          &lt;td&gt;配置自定义的 HttpMessageConverter&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;configurePathMatch(PathMatchConfigurer configurer)&lt;/td&gt;
          &lt;td&gt;PathMatchConfigurer configurer&lt;/td&gt;
          &lt;td&gt;配置路径匹配规则&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;configureViewResolvers(ViewResolverRegistry registry)&lt;/td&gt;
          &lt;td&gt;ViewResolverRegistry registry&lt;/td&gt;
          &lt;td&gt;配置视图解析器&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;extendHandlerExceptionResolvers(List&amp;lt;HandlerExceptionResolver&amp;gt; exceptionResolvers)&lt;/td&gt;
          &lt;td&gt;List&amp;lt;HandlerExceptionResolver&amp;gt; exceptionResolvers&lt;/td&gt;
          &lt;td&gt;扩展异常处理程序&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;extendMessageConverters(List&amp;lt;HttpMessageConverter&amp;lt;?&amp;gt;&amp;gt; converters)&lt;/td&gt;
          &lt;td&gt;List&amp;lt;HttpMessageConverter&amp;lt;?&amp;gt;&amp;gt; converters&lt;/td&gt;
          &lt;td&gt;扩展自定义的 HttpMessageConverter&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;extendInterceptors(List&amp;lt;HandlerInterceptor&amp;gt; interceptors)&lt;/td&gt;
          &lt;td&gt;List&amp;lt;HandlerInterceptor&amp;gt; interceptors&lt;/td&gt;
          &lt;td&gt;扩展拦截器&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;extendArgumentResolvers(List&amp;lt;HandlerMethodArgumentResolver&amp;gt; argumentResolvers)&lt;/td&gt;
          &lt;td&gt;List&amp;lt;HandlerMethodArgumentResolver&amp;gt; argumentResolvers&lt;/td&gt;
          &lt;td&gt;扩展自定义的 HandlerMethodArgumentResolver 用于解析方法参数。&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;extendReturnValueHandlers(List&amp;lt;HandlerMethodReturnValueHandler&amp;gt; returnValueHandlers)&lt;/td&gt;
          &lt;td&gt;List&amp;lt;HandlerMethodReturnValueHandler&amp;gt; returnValueHandlers&lt;/td&gt;
          &lt;td&gt;扩展自定义的 HandlerMethodReturnValueHandler 用于处理方法返回值。&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;extendViewResolvers(List&amp;lt;ViewResolver&amp;gt; viewResolvers)&lt;/td&gt;
          &lt;td&gt;List&amp;lt;ViewResolver&amp;gt; viewResolvers&lt;/td&gt;
          &lt;td&gt;扩展视图解析器&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;关联类&#34;&gt;关联类&lt;/h2&gt;
&lt;h3 id=&#34;webmvcconfigurationsupport&#34;&gt;WebMvcConfigurationSupport&lt;/h3&gt;
&lt;h3 id=&#34;enablewebmvc&#34;&gt;EnableWebMvc&lt;/h3&gt;
&lt;h2 id=&#34;接口常用方法&#34;&gt;接口常用方法&lt;/h2&gt;
&lt;p&gt;接口提供了将近20个方法对Spring的配置进行调整，本次只针对常用的Rest接口开发相关内容进行展开学习研究&lt;/p&gt;</description>
    </item>
    <item>
      <title>基于Spring initializr实现自己的项目模板</title>
      <link>http://blog.imcompany.cn/post/spring-initializr/</link>
      <pubDate>Tue, 15 Oct 2024 17:44:29 +0800</pubDate>
      <guid>http://blog.imcompany.cn/post/spring-initializr/</guid>
      <description>&lt;h2 id=&#34;介绍&#34;&gt;介绍&lt;/h2&gt;
&lt;p&gt;先前通过 Apache Maven Archetype 生成了一个项目脚手架1.0版本，模板比较固定，无法根据需要进行灵活定制，经过调研后，发现可基于&lt;a href=&#34;https://github.com/spring-io/start.spring.io&#34;&gt;Spring Starter&lt;/a&gt;项目进行定制，脚手架2.0版本也就应运而生。&lt;/p&gt;
&lt;h3 id=&#34;目标&#34;&gt;目标&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;快速创建最小可运行工程&lt;/li&gt;
&lt;li&gt;基础组件依赖管理
&lt;ol&gt;
&lt;li&gt;版本管理&lt;/li&gt;
&lt;li&gt;帮助信息&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;按需生成项目结构&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;最终效果&#34;&gt;最终效果&lt;/h3&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/M1kRNC.png&#34;/&gt; 
&lt;/figure&gt;

&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/eFelCJ.png&#34;/&gt; 
&lt;/figure&gt;

&lt;h2 id=&#34;实现&#34;&gt;实现&lt;/h2&gt;
&lt;h3 id=&#34;主流程&#34;&gt;主流程&lt;/h3&gt;
&lt;h4 id=&#34;获取配置&#34;&gt;获取配置&lt;/h4&gt;
&lt;p&gt;通过请求服务根路径获取脚手架信息，对应接口代码&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/hGib0q.png&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;如请求: &lt;a href=&#34;http://localhost:8080&#34;&gt;http://localhost:8080&lt;/a&gt; 会返回以下内容信息&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/uzQ6UA.png&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;接口返回了服务支持配置的元数据信息&lt;/p&gt;
&lt;h4 id=&#34;生成工程代码&#34;&gt;生成工程代码&lt;/h4&gt;
&lt;p&gt;用户选择配置相应功能后，点击生成按钮，会调用 &lt;a href=&#34;http://localhost:8080/start.zip&#34;&gt;http://localhost:8080/start.zip&lt;/a&gt; 接口将配置信息传给服务，服务根据信息生成代码&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/GAn0ja.png&#34;/&gt; 
&lt;/figure&gt;

&lt;h3 id=&#34;核心功能实现&#34;&gt;核心功能实现&lt;/h3&gt;
&lt;p&gt;项目工程由以下几方面组成:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;application.yml文件&lt;/li&gt;
&lt;li&gt;工程目录(controller, servier&amp;hellip;)&lt;/li&gt;
&lt;li&gt;auto_publish相关目录&lt;/li&gt;
&lt;li&gt;trpc_java.yaml文件&lt;/li&gt;
&lt;li&gt;配置相关
&lt;ol&gt;
&lt;li&gt;日志配置文件&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;web服务相关
&lt;ol&gt;
&lt;li&gt;httpApi接口&lt;/li&gt;
&lt;li&gt;httpApi实现类StartController&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Maven依赖管理&lt;/li&gt;
&lt;li&gt;主启动程序自定义&lt;/li&gt;
&lt;li&gt;测试辅助开发相关自定义
&lt;ol&gt;
&lt;li&gt;applicationTest&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/p5s2VW.png&#34;/&gt; 
&lt;/figure&gt;

&lt;h3 id=&#34;依赖管理&#34;&gt;依赖管理&lt;/h3&gt;
&lt;p&gt;根据现有常用的 &lt;strong&gt;Peacock&lt;/strong&gt; 框架功能包，依赖管理配置以下模块:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Starter&lt;/li&gt;
&lt;li&gt;Integration&lt;/li&gt;
&lt;li&gt;Provider&lt;/li&gt;
&lt;li&gt;Data&lt;/li&gt;
&lt;li&gt;Testing&lt;/li&gt;
&lt;li&gt;MQ&lt;/li&gt;
&lt;li&gt;Job&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;实践&#34;&gt;实践&lt;/h2&gt;
&lt;p&gt;生成一个最小可运行Web应用&lt;/p&gt;
&lt;h3 id=&#34;命令行快速生成&#34;&gt;命令行快速生成&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;curl -L &lt;span class=&#34;s1&#34;&gt;&amp;#39;http://localhost:8080/start.zip?type=peacock-project&amp;amp;bootVersion=1.5.7.RELEASE&amp;amp;groupId=com.yuewen.bookcoop&amp;amp;artifactId=solution_demo&amp;amp;name=solution_demo101&amp;amp;version=1.0.0-SNAPSHOT&amp;amp;language=java&amp;amp;packageName=com.yuewen.bookcoop.solution_demo&amp;amp;javaVersion=1.8&amp;amp;packaging=jar&amp;amp;description=solution_demo101&amp;amp;dependencies=integration-web&amp;amp;dependencies=peacock-test&amp;amp;dependencies=integration-common&amp;amp;dependencies=starter&amp;#39;&lt;/span&gt; -o solution_demo.zip
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;具体的依赖库元信息可以在根路径下请求获得，具体依赖信息为dependencies值对应id的值&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;idea中生成&#34;&gt;IDEA中生成&lt;/h3&gt;
&lt;h4 id=&#34;idea配置脚手架地址&#34;&gt;Idea配置脚手架地址&lt;/h4&gt;
&lt;p&gt;使用本地地址如: &lt;a href=&#34;http://localhost:8080&#34;&gt;http://localhost:8080&lt;/a&gt;&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/H1TIwb.png&#34;/&gt; 
&lt;/figure&gt;

&lt;h4 id=&#34;配置工程信息&#34;&gt;配置工程信息&lt;/h4&gt;
&lt;p&gt;填写好相关的业务信息与版本信息&lt;/p&gt;
&lt;h4 id=&#34;选择依赖模块&#34;&gt;选择依赖模块&lt;/h4&gt;
&lt;p&gt;Web应用需选择以下模块:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Peacock Trpc Starter&lt;/li&gt;
&lt;li&gt;Integration Web&lt;/li&gt;
&lt;li&gt;Integration Common&lt;/li&gt;
&lt;li&gt;Peacock Test&lt;/li&gt;
&lt;/ol&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://cdn.jsdelivr.net/gh/peng051410/bucket@main/img/9eAIUh.png&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;选择完成后点击 &lt;strong&gt;生成&lt;/strong&gt; 按钮生成代码&lt;/p&gt;</description>
    </item>
    <item>
      <title>记一次SpringWebflux框架下堆外OOM排查经历</title>
      <link>http://blog.imcompany.cn/post/springwebflux-leak-bug/</link>
      <pubDate>Thu, 31 Mar 2022 20:12:23 +0800</pubDate>
      <guid>http://blog.imcompany.cn/post/springwebflux-leak-bug/</guid>
      <description>&lt;h2 id=&#34;症状&#34;&gt;症状&lt;/h2&gt;
&lt;p&gt;生产环境业务页面打不开，看错误日志是 &lt;strong&gt;OutOfDirectMemoryError&lt;/strong&gt; (OOM)了，详情报错信息如下：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2022-03-21 06:00:00.541 &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;,&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;tafprx-asyrecv_9&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; ERROR r.c.p.Operators - &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;error,314&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; - Operator called default onErrorDropped
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;java.lang.OutOfMemoryError: Direct buffer memory
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at java.base/java.nio.Bits.reserveMemory&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;Bits.java:175&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at java.base/java.nio.DirectByteBuffer.&amp;lt;init&amp;gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;DirectByteBuffer.java:118&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at java.base/java.nio.ByteBuffer.allocateDirect&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;ByteBuffer.java:317&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at io.netty.buffer.PoolArena&lt;span class=&#34;nv&#34;&gt;$DirectArena&lt;/span&gt;.allocateDirect&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;PoolArena.java:632&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at io.netty.buffer.PoolArena&lt;span class=&#34;nv&#34;&gt;$DirectArena&lt;/span&gt;.newChunk&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;PoolArena.java:607&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at io.netty.buffer.PoolArena.allocateNormal&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;PoolArena.java:202&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at io.netty.buffer.PoolArena.tcacheAllocateSmall&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;PoolArena.java:172&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at io.netty.buffer.PoolArena.allocate&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;PoolArena.java:134&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at io.netty.buffer.PoolArena.allocate&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;PoolArena.java:126&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at io.netty.buffer.PooledByteBufAllocator.newDirectBuffer&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;PooledByteBufAllocator.java:395&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at io.netty.buffer.AbstractByteBufAllocator.directBuffer&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;AbstractByteBufAllocator.java:187&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at io.netty.buffer.AbstractByteBufAllocator.directBuffer&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;AbstractByteBufAllocator.java:178&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at io.netty.buffer.AbstractByteBufAllocator.buffer&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;AbstractByteBufAllocator.java:115&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at org.springframework.core.io.buffer.NettyDataBufferFactory.allocateBuffer&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;NettyDataBufferFactory.java:71&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at org.springframework.core.io.buffer.NettyDataBufferFactory.allocateBuffer&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;NettyDataBufferFactory.java:39&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at org.springframework.http.codec.json.AbstractJackson2Encoder.encodeValue&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;AbstractJackson2Encoder.java:236&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at org.springframework.http.codec.json.AbstractJackson2Encoder.lambda&lt;span class=&#34;nv&#34;&gt;$encode$0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;AbstractJackson2Encoder.java:150&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at reactor.core.publisher.FluxMapFuseable&lt;span class=&#34;nv&#34;&gt;$MapFuseableSubscriber&lt;/span&gt;.onNext&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;FluxMapFuseable.java:113&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at reactor.core.publisher.Operators&lt;span class=&#34;nv&#34;&gt;$MonoSubscriber&lt;/span&gt;.complete&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;Operators.java:1815&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at reactor.core.publisher.MonoCompletionStage.lambda&lt;span class=&#34;nv&#34;&gt;$subscribe$0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;MonoCompletionStage.java:82&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;CompletableFuture.java:859&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at java.base/java.util.concurrent.CompletableFuture.uniWhenCompleteStage&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;CompletableFuture.java:883&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at java.base/java.util.concurrent.CompletableFuture.whenComplete&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;CompletableFuture.java:2251&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at java.base/java.util.concurrent.CompletableFuture.whenComplete&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;CompletableFuture.java:143&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at reactor.core.publisher.MonoCompletionStage.subscribe&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;MonoCompletionStage.java:57&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at reactor.core.publisher.InternalMonoOperator.subscribe&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;InternalMonoOperator.java:64&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at reactor.core.publisher.MonoFlatMap&lt;span class=&#34;nv&#34;&gt;$FlatMapMain&lt;/span&gt;.onNext&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;MonoFlatMap.java:157&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at reactor.core.publisher.Operators&lt;span class=&#34;nv&#34;&gt;$MonoSubscriber&lt;/span&gt;.complete&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;Operators.java:1815&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at reactor.core.publisher.MonoFlatMap&lt;span class=&#34;nv&#34;&gt;$FlatMapInner&lt;/span&gt;.onNext&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;MonoFlatMap.java:249&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at reactor.core.publisher.FluxOnErrorResume&lt;span class=&#34;nv&#34;&gt;$ResumeSubscriber&lt;/span&gt;.onNext&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;FluxOnErrorResume.java:79&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at reactor.core.publisher.FluxPeek&lt;span class=&#34;nv&#34;&gt;$PeekSubscriber&lt;/span&gt;.onNext&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;FluxPeek.java:199&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at reactor.core.publisher.FluxPeek&lt;span class=&#34;nv&#34;&gt;$PeekSubscriber&lt;/span&gt;.onNext&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;FluxPeek.java:199&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at reactor.core.publisher.MonoIgnoreThen&lt;span class=&#34;nv&#34;&gt;$ThenIgnoreMain&lt;/span&gt;.complete&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;MonoIgnoreThen.java:284&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at reactor.core.publisher.MonoIgnoreThen&lt;span class=&#34;nv&#34;&gt;$ThenIgnoreMain&lt;/span&gt;.onNext&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;MonoIgnoreThen.java:187&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at reactor.core.publisher.Operators&lt;span class=&#34;nv&#34;&gt;$MonoSubscriber&lt;/span&gt;.complete&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;Operators.java:1815&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        at reactor.core.publisher.MonoFlatMap&lt;span class=&#34;nv&#34;&gt;$FlatMapMain&lt;/span&gt;.onNext&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;MonoFlatMap.java:151&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;根据报错的堆栈，找到 &lt;strong&gt;AbstractJackson2Encoder:236&lt;/strong&gt; 行，调试发现框架使用的buffer在最后都进行了释放，看着没问题。&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
