ou can implement simple factory bean to do the conditional wiring. Such factory bean can contain complex conditioning logic:
<span class="kwd">public<span class="pln"> <span class="typ">MyBeanFactoryBean<span class="pln"> <span class="kwd">implements<span class="pln"> <span class="typ">FactoryBean<span class="pun"><<span class="typ">MyBean<span class="pun">><span class="pln"> <span class="pun">{<span class="pln">
<span class="com">// Using app context instead of bean references so that the unused <span class="pln">
<span class="com">// dependency can be left uninitialized if it is lazily initialized<span class="pln">
<span class="lit">@Autowired<span class="pln">
<span class="kwd">private<span class="pln"> <span class="typ">ApplicationContext<span class="pln"> applicationContext<span class="pun">;<span class="pln">
<span class="kwd">public<span class="pln"> <span class="typ">MyBean<span class="pln"> getObject<span class="pun">()<span class="pln"> <span class="pun">{<span class="pln">
<span class="typ">MyBean<span class="pln"> myBean <span class="pun">=<span class="pln"> <span class="kwd">new<span class="pln"> <span class="typ">MyBean<span class="pun">();<span class="pln">
<span class="kwd">if<span class="pln"> <span class="pun">(<span class="kwd">true<span class="pln"> <span class="com">/* some condition */<span class="pun">)<span class="pln"> <span class="pun">{<span class="pln">
myBean<span class="pun">.<span class="pln">setDependency<span class="pun">(<span class="pln">applicationContext<span class="pun">.<span class="pln">getBean<span class="pun">(<span class="typ">DependencyX<span class="pun">.<span class="kwd">class<span class="pun">));<span class="pln">
<span class="pun">}<span class="pln"> <span class="kwd">else<span class="pln"> <span class="pun">{<span class="pln">
myBean<span class="pun">.<span class="pln">setDependency<span class="pun">(<span class="pln">applicationContext<span class="pun">.<span class="pln">getBean<span class="pun">(<span class="typ">DependencyY<span class="pun">.<span class="kwd">class<span class="pun">));<span class="pln">
<span class="pun">}<span class="pln">
<span class="kwd">return<span class="pln"> myBean<span class="pun">;<span class="pln">
<span class="pun">}<span class="pln">
<span class="com">// Implementation of isSingleton => false and getObjectType<span class="pln">
<span class="pun">}</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>
Maybe a bit better approach is if you use factory bean to create the dependency bean in case you want to have only one such bean in your application context:
<span class="kwd">public<span class="pln"> <span class="typ">MyDependencyFactoryBean<span class="pln"> <span class="kwd">implements<span class="pln"> <span class="typ">FactoryBean<span class="pun"><<span class="typ">MyDependency<span class="pun">><span class="pln"> <span class="pun">{<span class="pln">
<span class="kwd">public<span class="pln"> <span class="typ">MyDependency<span class="pln"> getObject<span class="pun">()<span class="pln"> <span class="pun">{<span class="pln">
<span class="kwd">if<span class="pln"> <span class="pun">(<span class="kwd">true<span class="pln"> <span class="com">/* some condition */<span class="pun">)<span class="pln"> <span class="pun">{<span class="pln">
<span class="kwd">return<span class="pln"> <span class="kwd">new<span class="pln"> <span class="typ">MyDependencyX<span class="pun">();<span class="pln">
<span class="pun">}<span class="pln"> <span class="kwd">else<span class="pln"> <span class="pun">{<span class="pln">
<span class="kwd">return<span class="pln"> <span class="kwd">new<span class="pln"> <span class="typ">MyDependencyY<span class="pun">();<span class="pln">
<span class="pun">}<span class="pln">
<span class="pun">}<span class="pln">
<span class="com">// Implementation of isSingleton => false and getObjectType<span class="pln">
<span class="pun">}</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>
With SpEL there are many possibilities. Most common are system property based conditions:
<span class="tag"><bean<span class="pln"> <span class="atn">class<span class="pun">=<span class="atv">"com.example.MyBean"<span class="tag">><span class="pln">
<span class="tag"><property<span class="pln"> <span class="atn">name<span class="pun">=<span class="atv">"dependency"<span class="pln"> <span class="atn">value<span class="pun">=<span class="atv">"#{systemProperties['foo'] == 'bar' ? dependencyX : dependencyY}"<span class="pln"> <span class="tag">/></span></span></span></span></span></span></span></span></span></property<span></span></span></span></span></span></span></bean<span></span>
You can have property placeholder resolve your bean reference. The dependency name can be part of the application configuration.
<span class="tag"><bean<span class="pln"> <span class="atn">class<span class="pun">=<span class="atv">"com.example.MyBean"<span class="tag">><span class="pln">
<span class="tag"><property<span class="pln"> <span class="atn">name<span class="pun">=<span class="atv">"dependency"<span class="pln"> <span class="atn">ref<span class="pun">=<span class="atv">"${dependencyName}"<span class="pln"> <span class="tag">/></span></span></span></span></span></span></span></span></span></property<span></span></span></span></span></span></span></bean<span></span>
Usually the condition you want to evaluate means that a whole set of beans should or should not be registered. Spring profiles can be used for this:
<span class="com"><!-- Default dependency which is referred by myBean --><span class="pln">
<span class="tag"><bean<span class="pln"> <span class="atn">id<span class="pun">=<span class="atv">"dependency"<span class="pln"> <span class="atn">class<span class="pun">=<span class="atv">"com.example.DependencyX"<span class="pln"> <span class="tag">/><span class="pln">
<span class="tag"><beans<span class="pln"> <span class="atn">profile<span class="pun">=<span class="atv">"myProfile"<span class="tag">><span class="pln">
<span class="com"><!-- Override dependency
definition if myProfile is active --><span class="pln">
<span class="tag"><bean<span class="pln"> <span class="atn">id<span class="pun">=<span class="atv">"dependency"<span class="pln"> <span class="atn">class<span class="pun">=<span class="atv">"com.example.DependencyY"<span class="pln"> <span class="tag">/></span></span></span></span></span></span></span></span></span></bean<span></span></span></span></span></span></span></span></span></beans<span></span></span></span></span></span></span></span></span></span></span></span></bean<span></span></span></span>
Other methods can mark the bean definition as lazy-init="true"
, but the definition will be still registered inside application context (and making your life harder when using unqualified autowiring). You can also use profiles with @Component
based beans via @Profile
annotation.
This is why Java based config is being so popular as you can do:
<span class="lit">@Bean<span class="pln">
<span class="kwd">public<span class="pln"> <span class="typ">MyBean<span class="pln"> myBean<span class="pun">()<span class="pln"> <span class="pun">{<span class="pln">
<span class="typ">MyBean<span class="pln"> myBean <span class="pun">=<span class="pln"> <span class="kwd">new<span class="pln"> <span class="typ">MyBean<span class="pun">();<span class="pln">
<span class="kwd">if<span class="pln"> <span class="pun">(<span class="kwd">true<span class="pln"> <span class="com">/* some condition */<span class="pun">)<span class="pln"> <span class="pun">{<span class="pln">
myBean<span class="pun">.<span class="pln">setDependency<span class="pun">(<span class="pln">dependencyX<span class="pun">());<span class="pln">
<span class="pun">}<span class="pln"> <span class="kwd">else<span class="pln"> <span class="pun">{<span class="pln">
myBean<span class="pun">.<span class="pln">setDependency<span class="pun">(<span class="pln">dependencyY<span class="pun">());<span class="pln">
<span class="pun">}<span class="pln">
<span class="kwd">return<span class="pln"> myBean<span class="pun">;<span class="pln">
<span class="pun">}</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>
Of course you can use more or less all configuration methods in the java based config as well (via @Profile
, @Value
or @Qualifier
+ @Autowired
).
Spring offers numerous hook points and SPIs, where you can participate in the application context life-cycle. This section requires a bit more knowledge of Spring’s inner workings.
BeanFactoryPostProcessor
s can read and alter bean definitions (e.g. property placeholder ${}
resolution is implemented this way).
BeanPostProcessor
s can process bean instances. It is possible to check freshly created bean and play with it (e.g. @Scheduled
annotation processing is implemented this way).
MergedBeanDefinitionPostProcessor
is extension of bean post processor and can alter the bean definition just before it is being instantiated (@Autowired
annotation processing is implemented this way).
UPDATE Oct 2015
-
Spring 4 has added a new method how to do conditional bean registration via
@Conditional
annotation. That is worth checking as well. -
Of course there are numerous other ways with Spring Boot alone via its
@ConditionalOn*
. -
Also note that both
@Import
and@ComponentScan
(and their XML counterparts) undergo property resolution (i.e. you can use${}
).
Original: https://www.cnblogs.com/goody9807/p/7659993.html
Author: PointNet
Title: How to do conditional auto-wiring in Spring?
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/540020/
转载文章受原作者版权保护。转载请注明原作者出处!