BeanDefinitionRegistryPostProcessor就是用來自定義bean的,並手動注入到Spring的容器裏面,有時候覺得定義bean直接使用註解或者xml配置更方便,但是Spring既然提供,肯定是有道理,嘗試一下。
這種使用一般是自己用來封裝一些擴展插件的時候使用。
BeanDefinitionRegistryPostProcessor 就是一個定義很簡單的接口,要想實現實現自定義bean只需要實現這個接口就行。
/**
* Extension to the standard {@link BeanFactoryPostProcessor} SPI, allowing for
* the registration of further bean definitions <i>before</i> regular
* BeanFactoryPostProcessor detection kicks in. In particular,
* BeanDefinitionRegistryPostProcessor may register further bean definitions
* which in turn define BeanFactoryPostProcessor instances.
*
* @author Juergen Hoeller
* @since 3.0.1
* @see org.springframework.context.annotation.ConfigurationClassPostProcessor
*/
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean definition registry after its
* standard initialization. All regular bean definitions will have been loaded,
* but no beans will have been instantiated yet. This allows for adding further
* bean definitions before the next post-processing phase kicks in.
* @param registry the bean definition registry used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
自定義實現bean定義
package com.madman.annotation.springextension;
import com.madman.annotation.entity.Blue;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
/**
* <pre>
* 【類型】: CustomBeanDefinitionRegistryPostProcessor <br/>
* 【作用】: 請填寫此類的作用<br/>
* 【時間】:2019/1/3 14:50 <br/>
* 【作者】:madman <br/>
* </pre>
*/
@Configuration
@Component
public class CustomBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition("com.madman.annotation.entity.Blue");
beanDefinitionBuilder.addPropertyValue("name", "小鵬一號");
beanDefinitionBuilder.addPropertyValue("age", "18");
BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Blue.class).getBeanDefinition();
beanDefinition.getPropertyValues().add("name", "小鵬二號");
beanDefinition.getPropertyValues().add("age", "28");
registry.registerBeanDefinition("bule_01", beanDefinitionBuilder.getBeanDefinition());
registry.registerBeanDefinition("bule_02", beanDefinition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
自定義bean最重要的類就是BeanDefinition接口了,這個接口裏面定義了註冊bean的各種屬性,一般我們定義bean的時候都是用的BeanDefinitionBuilder這個spring提供的定義bean的工具類,上面的這個自定義的bean裏面也是用的這個來創建bean。
上面的代碼使用了兩種形式創建了bean,
這種形式是直接通過類名的全路徑進行定義的,定義好之後可以addPropertyValue方法來設置屬性。
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition("com.madman.annotation.entity.Blue");
beanDefinitionBuilder.addPropertyValue("name", "小鵬一號");
這種形式就是通過Class的形式來定義bean的,這個形式得到的是BeanDefinition對象,所以設置屬性的方式和上面不一樣。
BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Blue.class).getBeanDefinition();
beanDefinition.getPropertyValues().add("name", "小鵬二號");
最後註冊bean使用的是registry的registerBeanDefinition方法來註冊bean,registry屬性也有很多方法,是否包含,移除bean等操作,可以用來判斷bean是否存在或者名字是否存在等一些操作。
registry.registerBeanDefinition("bule_02", beanDefinition);
自定義bean之後,就需要使用這類注入到spring容器裏面去,這裏我直接使用了@Configuration,@Component這兩個註解,把這類當成一個組件,掃描的時候直接掃進去就行了。
最後測試的結果是這樣的,屬性和上面是一一對應的。
public class start_1 {
public static void main(String[] args) {
AnnotationConfigApplicationContext annotation = new AnnotationConfigApplicationContext(Config_1.class);
Map<String, Blue> beansOfType = annotation.getBeansOfType(Blue.class);
for (String s : beansOfType.keySet()) {
System.out.println("名字是:" + s);
System.out.println(beansOfType.get(s).toString());
}
}
}
無參數構造函數
無參數構造函數
無參數構造函數
名字是:blue
Blue{name='19', age=12}
名字是:bule_01
Blue{name='小鵬一號', age=18}
名字是:bule_02
Blue{name='小鵬二號', age=28}