Spring擴展BeanFactoryPostProcessor使用技巧詳解
1、Spring 擴展點 BeanFactoryPostProcessor 使用技巧
方法
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
其中提供一個 ConfigurableListableBeanFactory 回調對象,里面提供了很多框架內部使用的方法,建議的話使用它的實現(xiàn)類去注冊 Bean 的信息。
不建議使用里面的方法直接實例化對象,因為過早的創(chuàng)建對象會導致后續(xù) Spring 一些對 Bean 修飾執(zhí)行不到,生命周期不完整。
1.1、BeanDefinitionRegistryPostProcessor
BeanFactoryPostProcessor 的實現(xiàn)類。
調用位置
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;
一般來使用當前方法來注冊 BeanDefinition。
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException;
第一個參數(shù)填的是 Bean 的名稱,第二個就是 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<>();
// 當前會掃描該類下所有的類文件
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));
}
}
以上方式會將包下的所有類都掃描到然后添加到 Spring 容器當中,以上代碼參考于 Mybatis 注冊 Bean 的方式。
1.1.2、AnnotatedGenericBeanDefinition
這種方式就很直接了。直接 new 一個對象將需要的 Bean 的 class 放進去。
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(Test.class);
1.1.3、RootBeanDefinition
這個實現(xiàn)類和上面很類似,只不過多了幾個構造方法:
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Test.class);
public RootBeanDefinition(String beanClassName);
最主要的還是以下的構造器:
public RootBeanDefinition(@Nullable Class<?> beanClass, @Nullable ConstructorArgumentValues cargs,@Nullable MutablePropertyValues pvs);
這個的話多了幾個參數(shù),ConstructorArgumentValues,看名字就大概可以猜的出是傳構造參數(shù)的。當我們需要創(chuàng)建的 Bean 是有參構造器時,我們就可以使用當前方法將構造參數(shù)傳遞進去。
ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
// 添加構造參數(shù)
constructorArgumentValues.addGenericArgumentValue(111);
這個添加的順序就代表了構造器參數(shù)的順序。
第二個對象我們可以通過它去修改類屬性的值。
// 修改類屬性的值
MutablePropertyValues mutablePropertyValues = new MutablePropertyValues();
mutablePropertyValues.addPropertyValue("age",555);
當然我們也可以通過其他工具類去創(chuàng)建:
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(TestBean.class);
beanDefinitionBuilder.addConstructorArgValue(1);registry.registerBeanDefinition("testBean",beanDefinitionBuilder.getBeanDefinition());
1.2、環(huán)境變量 Environment
一般我們創(chuàng)建 Bean 的時候都喜歡去讀 yml 的配置文件,但是在當前對象中,直接使用注入的方式是獲取不到配置文件的:
@Value("${test.case}")
private String name;
@Autowired
private Environment environment;
這時候我們可以配合另外一個擴展點去獲取環(huán)境變量。因為在當前擴展點執(zhí)行的之后,Environment 是已經創(chuàng)建了放置進了 IOC 容器當中,我們需要通過下面的方式去獲?。?/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擴展BeanFactoryPostProcessor使用技巧詳解的詳細內容,更多關于Spring擴展BeanFactoryPostProcessor的資料請關注腳本之家其它相關文章!
相關文章
Java獲取resources下文件路徑的幾種方法及遇到的問題
這篇文章主要給大家介紹了關于Java獲取resources下文件路徑的幾種方法及遇到的問題,在Java開發(fā)中經常需要讀取項目中resources目錄下的文件或獲取資源路徑,需要的朋友可以參考下2023-12-12
Spring MVC參數(shù)校驗詳解(關于`@RequestBody`返回`400`)
這篇文章主要介紹了Spring MVC參數(shù)校驗的相關資料,主要是針對`@RequestBody`返回`400`的問題,文中通過示例代碼介紹的非常詳細,對大家具有一定的參考學習價值,需要的朋友們下面跟著小編來一起學習學習吧。2017-08-08
MyBatis 動態(tài) SQL 優(yōu)化之標簽的實戰(zhàn)與技巧(常見用法)
本文通過詳細的示例和實際應用場景,介紹了如何有效利用這些標簽來優(yōu)化 MyBatis 配置,提升開發(fā)效率,確保 SQL 的高效執(zhí)行和安全性,感興趣的朋友跟隨小編一起看看吧2025-04-04
如何實現(xiàn)java8 list按照元素的某個字段去重
這篇文章主要介紹了如何實現(xiàn)java8 list按照元素的某個字段去重,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,,需要的朋友可以參考下2019-06-06

