Spring擴(kuò)展BeanFactoryPostProcessor使用技巧詳解
1、Spring 擴(kuò)展點(diǎn) BeanFactoryPostProcessor 使用技巧
方法
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
其中提供一個(gè) ConfigurableListableBeanFactory 回調(diào)對(duì)象,里面提供了很多框架內(nèi)部使用的方法,建議的話使用它的實(shí)現(xiàn)類去注冊(cè) Bean 的信息。
不建議使用里面的方法直接實(shí)例化對(duì)象,因?yàn)檫^早的創(chuàng)建對(duì)象會(huì)導(dǎo)致后續(xù) Spring 一些對(duì) Bean 修飾執(zhí)行不到,生命周期不完整。
1.1、BeanDefinitionRegistryPostProcessor
BeanFactoryPostProcessor 的實(shí)現(xiàn)類。
調(diào)用位置
org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List<org.springframework.beans.factory.config.BeanFactoryPostProcessor>)
方法
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
一般來使用當(dāng)前方法來注冊(cè) BeanDefinition。
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException;
第一個(gè)參數(shù)填的是 Bean 的名稱,第二個(gè)就是 Bean 的信息。一般可以使用以下方式去獲取 BeanDefinition。
1.1.1、ScannedGenericBeanDefinition
public class Test { private static final PathMatchingResourcePatternResolver PATTERN_RESOLVER = new PathMatchingResourcePatternResolver(); private static final CachingMetadataReaderFactory READER_FACTORY = new CachingMetadataReaderFactory(); static final String DEFAULT_RESOURCE_PATTERN = "**/*.class"; public static void main(String[] args) throws IOException { System.out.println(doScan("com.rookie.mybatis.study")); } private static List<ScannedGenericBeanDefinition> doScan(String basePackage) throws IOException { basePackage = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '/' + DEFAULT_RESOURCE_PATTERN; List<ScannedGenericBeanDefinition> result = new ArrayList<>(); // 當(dāng)前會(huì)掃描該類下所有的類文件 Resource[] resources = PATTERN_RESOLVER.getResources(basePackage); for (Resource resource : resources) { MetadataReader metadataReader = READER_FACTORY.getMetadataReader(resource); ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); sbd.setSource(resource); result.add(sbd); } return result; } private static String resolveBasePackage(String basePackage) { return ClassUtils.convertClassNameToResourcePath(new StandardEnvironment().resolveRequiredPlaceholders(basePackage)); } }
以上方式會(huì)將包下的所有類都掃描到然后添加到 Spring 容器當(dāng)中,以上代碼參考于 Mybatis 注冊(cè) Bean 的方式。
1.1.2、AnnotatedGenericBeanDefinition
這種方式就很直接了。直接 new 一個(gè)對(duì)象將需要的 Bean 的 class 放進(jìn)去。
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(Test.class);
1.1.3、RootBeanDefinition
這個(gè)實(shí)現(xiàn)類和上面很類似,只不過多了幾個(gè)構(gòu)造方法:
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Test.class);
public RootBeanDefinition(String beanClassName);
最主要的還是以下的構(gòu)造器:
public RootBeanDefinition(@Nullable Class<?> beanClass, @Nullable ConstructorArgumentValues cargs,@Nullable MutablePropertyValues pvs);
這個(gè)的話多了幾個(gè)參數(shù),ConstructorArgumentValues,看名字就大概可以猜的出是傳構(gòu)造參數(shù)的。當(dāng)我們需要?jiǎng)?chuàng)建的 Bean 是有參構(gòu)造器時(shí),我們就可以使用當(dāng)前方法將構(gòu)造參數(shù)傳遞進(jìn)去。
ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues(); // 添加構(gòu)造參數(shù) constructorArgumentValues.addGenericArgumentValue(111);
這個(gè)添加的順序就代表了構(gòu)造器參數(shù)的順序。
第二個(gè)對(duì)象我們可以通過它去修改類屬性的值。
// 修改類屬性的值 MutablePropertyValues mutablePropertyValues = new MutablePropertyValues(); mutablePropertyValues.addPropertyValue("age",555);
當(dāng)然我們也可以通過其他工具類去創(chuàng)建:
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(TestBean.class); beanDefinitionBuilder.addConstructorArgValue(1);registry.registerBeanDefinition("testBean",beanDefinitionBuilder.getBeanDefinition());
1.2、環(huán)境變量 Environment
一般我們創(chuàng)建 Bean 的時(shí)候都喜歡去讀 yml 的配置文件,但是在當(dāng)前對(duì)象中,直接使用注入的方式是獲取不到配置文件的:
@Value("${test.case}") private String name; @Autowired private Environment environment;
這時(shí)候我們可以配合另外一個(gè)擴(kuò)展點(diǎn)去獲取環(huán)境變量。因?yàn)樵诋?dāng)前擴(kuò)展點(diǎn)執(zhí)行的之后,Environment 是已經(jīng)創(chuàng)建了放置進(jìn)了 IOC 容器當(dāng)中,我們需要通過下面的方式去獲?。?/p>
@Component public class Test implements BeanDefinitionRegistryPostProcessor, ApplicationContextAware { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { Environment environment = applicationContext.getEnvironment(); String xx = environment.getProperty("xx"); } }
以上就是Spring擴(kuò)展BeanFactoryPostProcessor使用技巧詳解的詳細(xì)內(nèi)容,更多關(guān)于Spring擴(kuò)展BeanFactoryPostProcessor的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
說說@ModelAttribute在父類和子類中的執(zhí)行順序
這篇文章主要介紹了@ModelAttribute在父類和子類中的執(zhí)行順序,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06springboot 啟動(dòng)如何修改application.properties的參數(shù)
這篇文章主要介紹了springboot 啟動(dòng)如何修改application.properties的參數(shù)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08Java中的三種校驗(yàn)注解的使用(@Valid,@Validated和@PathVariable)
本文主要介紹了Java中的三種校驗(yàn)注解的使用(@Valid,@Validated和@PathVariable),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04mybatis如何通過接口查找對(duì)應(yīng)的mapper.xml及方法執(zhí)行詳解
這篇文章主要給大家介紹了利用mybatis如何通過接口查找對(duì)應(yīng)的mapper.xml及方法執(zhí)行的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面跟著小編一起來學(xué)習(xí)學(xué)習(xí)吧。2017-06-06Hikari連接池使用SpringBoot配置JMX監(jiān)控實(shí)現(xiàn)
Hikari是Spring Boot默認(rèn)的數(shù)據(jù)庫連接池。區(qū)別于C3P0直接通過連接池對(duì)象獲取各項(xiàng)狀態(tài)指標(biāo),Hikari需要通過JMX來獲取。本文就詳細(xì)的來介紹一下,感興趣的可以了解一下2021-07-07SpringBoot MDC全鏈路調(diào)用日志跟蹤實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了SpringBoot MDC全鏈路調(diào)用日志跟蹤實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02