Spring扩展BeanFactoryPostProcessor使用技巧详解

 更新时间:2022年09月27日 16:30:51   作者:rookie_only  
这篇文章主要为大家介绍了Spring扩展BeanFactoryPostProcessor使用技巧详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

1、Spring 扩展点 BeanFactoryPostProcessor 使用技巧

方法

void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) 
throws BeansException;

其中提供一个 ConfigurableListableBeanFactory 回调对象,里面提供了很多框架内部使用的方法,建议的话使用它的实现类去注册 Bean 的信息。

不建议使用里面的方法直接实例化对象,因为过早的创建对象会导致后续 Spring 一些对 Bean 修饰执行不到,生命周期不完整。

1.1、BeanDefinitionRegistryPostProcessor

BeanFactoryPostProcessor 的实现类。

调用位置

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;

第一个参数填的是 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

这个实现类和上面很类似,只不过多了几个构造方法:

RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Test.class);
public RootBeanDefinition(String beanClassName);

最主要的还是以下的构造器:

public RootBeanDefinition(@Nullable Class<?> beanClass, @Nullable ConstructorArgumentValues cargs,@Nullable MutablePropertyValues pvs);

这个的话多了几个参数,ConstructorArgumentValues,看名字就大概可以猜的出是传构造参数的。当我们需要创建的 Bean 是有参构造器时,我们就可以使用当前方法将构造参数传递进去。

        ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
        //        添加构造参数        
        constructorArgumentValues.addGenericArgumentValue(111);

这个添加的顺序就代表了构造器参数的顺序。

第二个对象我们可以通过它去修改类属性的值。

// 修改类属性的值
MutablePropertyValues mutablePropertyValues = new MutablePropertyValues();
mutablePropertyValues.addPropertyValue("age",555);

当然我们也可以通过其他工具类去创建:

BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(TestBean.class);
beanDefinitionBuilder.addConstructorArgValue(1);registry.registerBeanDefinition("testBean",beanDefinitionBuilder.getBeanDefinition());

1.2、环境变量 Environment

一般我们创建 Bean 的时候都喜欢去读 yml 的配置文件,但是在当前对象中,直接使用注入的方式是获取不到配置文件的:

@Value("${test.case}")
private String name;
@Autowired
private Environment environment;

这时候我们可以配合另外一个扩展点去获取环境变量。因为在当前扩展点执行的之后,Environment 是已经创建了放置进了 IOC 容器当中,我们需要通过下面的方式去获取:

@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 IO流对象的序列化和反序列化实例详解

    Java IO流对象的序列化和反序列化实例详解

    这篇文章主要介绍了Java IO流对象的序列化和反序列化实例详解的相关资料,需要的朋友可以参考下
    2017-05-05
  • Spring框架中的@Conditional系列注解详解

    Spring框架中的@Conditional系列注解详解

    这篇文章主要介绍了Spring框架中的@Conditional系列注解详解,我们需要一个类实现Spring提供的Condition接口,它会匹配@Conditional所符合的方法,然后我们可以使用我们在@Conditional注解中定义的类来检查,需要的朋友可以参考下
    2024-01-01
  • web中拖拽排序和java后台交互实现方法示例

    web中拖拽排序和java后台交互实现方法示例

    这篇文章主要给大家介绍了关于web中拖拽排序和java后台交互实现的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-12-12
  • Spring IO Platform简单介绍

    Spring IO Platform简单介绍

    这篇文章主要介绍了Spring IO Platform简单介绍,具有一定借鉴价值,需要的朋友可以参考下
    2017-12-12
  • Java线程实现时间动态显示

    Java线程实现时间动态显示

    这篇文章主要为大家详细介绍了Java线程实现时间动态显示,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-04-04
  • Java获取resources下文件路径的几种方法及遇到的问题

    Java获取resources下文件路径的几种方法及遇到的问题

    这篇文章主要给大家介绍了关于Java获取resources下文件路径的几种方法及遇到的问题,在Java开发中经常需要读取项目中resources目录下的文件或获取资源路径,需要的朋友可以参考下
    2023-12-12
  • Spring MVC参数校验详解(关于`@RequestBody`返回`400`)

    Spring MVC参数校验详解(关于`@RequestBody`返回`400`)

    这篇文章主要介绍了Spring MVC参数校验的相关资料,主要是针对`@RequestBody`返回`400`的问题,文中通过示例代码介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面跟着小编来一起学习学习吧。
    2017-08-08
  • 详解Java动态加载数据库驱动

    详解Java动态加载数据库驱动

    本篇文章主要介绍了详解Java动态加载数据库驱动,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

    MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

    本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化 MyBatis 配置,提升开发效率,确保 SQL 的高效执行和安全性,感兴趣的朋友跟随小编一起看看吧
    2025-04-04
  • 如何实现java8 list按照元素的某个字段去重

    如何实现java8 list按照元素的某个字段去重

    这篇文章主要介绍了如何实现java8 list按照元素的某个字段去重,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,,需要的朋友可以参考下
    2019-06-06

最新评论