Spring扩展BeanFactoryPostProcessor使用技巧详解

目录
  • 1、Spring 扩展点 BeanFactoryPostProcessor 使用技巧
    • 1.1、BeanDefinitionRegistryPostProcessor
      • 1.1.1、ScannedGenericBeanDefinition
      • 1.1.2、AnnotatedGenericBeanDefinition
      • 1.1.3、RootBeanDefinition
    • 1.2、环境变量 Environment

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的资料请关注我们其它相关文章!

(0)

相关推荐

  • Spring源码BeanFactoryPostProcessor详解

    Spring源码分析-BeanFactoryPostProcessor BeanFactoryPostProcessor接口是Spring提供的对Bean的扩展点,它的子接口是BeanDefinitionRegistryPostProcessor @FunctionalInterface public interface BeanFactoryPostProcessor { void postProcessBeanFactory(ConfigurableListableBeanFactory b

  • Spring注解驱动扩展原理BeanFactoryPostProcessor

    1.扩展原理-BeanFactoryPostProcessor BeanFactoryPostProcessor * 扩展原理: * BeanPostProcessor:bean后置处理器,bean创建对象初始化前后进行拦截工作的 * * 1.BeanFactoryPostProcessor:beanFactory的后置处理器: * 在BeanFactory标准初始化之后调用,来定制和修改BeanFactory的内容: * 所有的bean定义已经保存加载到beanFactory,但是bean的实

  • Spring的BeanFactoryPostProcessor接口示例代码详解

    接口简介 BeanFactoryPostProcessor 接口是 Spring 初始化 BeanFactory 时对外暴露的扩展点,Spring IoC 容器允许 BeanFactoryPostProcessor 在容器实例化任何 bean 之前读取 bean 的定义,并可以修改它. BeanDefinitionRegistryPostProcessor 继承自 BeanFactoryPostProcessor,比 BeanFactoryPostProcessor 具有更高的优先级,主要用来在

  • Spring扩展BeanFactoryPostProcessor使用技巧详解

    目录 1.Spring 扩展点 BeanFactoryPostProcessor 使用技巧 1.1.BeanDefinitionRegistryPostProcessor 1.1.1.ScannedGenericBeanDefinition 1.1.2.AnnotatedGenericBeanDefinition 1.1.3.RootBeanDefinition 1.2.环境变量 Environment 1.Spring 扩展点 BeanFactoryPostProcessor 使用技巧 方法

  • Spring AOP的实现原理详解及实例

    Spring AOP的实现原理详解及实例 spring 实现AOP是依赖JDK动态代理和CGLIB代理实现的. 以下是JDK动态代理和CGLIB代理简单介绍 JDK动态代理:其代理对象必须是某个接口的实现,它是通过在运行期间创建一个接口的实现类来完成对目标对象的代理. CGLIB代理:实现原理类似于JDK动态代理,只是它在运行期间生成的代理对象是针对目标类扩展的子类.CGLIB是高效的代码生成包,底层是依靠ASM(开源的Java字节码编辑类库)操作字节码实现的,性能比JDK强. 在Spring中

  • Spring Boot 集成MyBatis 教程详解

    Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者. 在集成MyBatis前,我们先配置一个druid数据源. Spring Boot 系列 1.Spring Boot 入门 2.Spring Boot 属性配置

  • Java 自定义Spring框架与核心功能详解

    目录 Spring核心功能结构 核心容器 spring-beans和spring-core模块 spring-context模块 spring-context-support模块 spring-context-indexer模块 spring-expression模块 AOP和设备支持 数据访问与集成 Web组件 通信报文 集成测试 bean概述 在上一讲中,我们对Spring的基本使用进行了一个简单的回顾,接下来,我们就来看一下Spring核心功能结构. Spring核心功能结构 Spring

  • php安全攻防利用文件上传漏洞与绕过技巧详解

    目录 前言 文件上传漏洞的一些场景 场景一:前端js代码白名单判断.jpg|.png|.gif后缀 场景二:后端PHP代码检查Content-type字段 场景三:代码黑名单判断.asp|.aspx|.php|.jsp后缀 场景四:代码扩大黑名单判断 绕过方式--htaccsess: 绕过方式--大小写绕过: 场景五:一些复合判断 空格.点绕过(windows) ::$DATA绕过(windows) 双写绕过 %00截断 %0a绕过 图片马绕过 二次渲染绕过 条件竞争 /.绕过 前言 文件上传漏

  • Golang 内存管理简单技巧详解

    目录 引言 预先分配切片 结构中的顺序字段 使用 map[string]struct{} 而不是 map[string]bool 引言 除非您正在对服务进行原型设计,否则您可能会关心应用程序的内存使用情况.内存占用更小,基础设施成本降低,扩展变得更容易/延迟. 尽管 Go 以不消耗大量内存而闻名,但仍有一些方法可以进一步减少消耗.其中一些需要大量重构,但很多都很容易做到. 预先分配切片 数组是具有连续内存的相同类型的集合.数组类型定义指定长度和元素类型.数组的主要问题是它们的大小是固定的——它们

  • Spring Boot整合Kafka教程详解

    目录 正文 步骤一:添加依赖项 步骤二:配置 Kafka 步骤三:创建一个生产者 步骤四:创建一个消费者 正文 本教程将介绍如何在 Spring Boot 应用程序中使用 Kafka.Kafka 是一个分布式的发布-订阅消息系统,它可以处理大量数据并提供高吞吐量. 在本教程中,我们将使用 Spring Boot 2.5.4 和 Kafka 2.8.0. 步骤一:添加依赖项 在 pom.xml 中添加以下依赖项: <dependency> <groupId>org.springfra

  • Spring boot 使用mysql实例详解

    Spring boot 使用mysql实例详解 开发阶段用 H2即可,上线时,通过以下配置切换到mysql,spring boot将使用这个配置覆盖默认的H2. 1.建立数据库: mysql -u root CREATE DATABASE springbootdb 2.pom.xml: <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId&g

  • myeclipse8.5优化技巧详解

    还在为自己的配置低而抛弃MyEclipse8.5?还在为那低下的速度而苦恼吗?下面我们看看myeclipse8.5优化技巧的具体方法. 取消自动validation validation有一堆,什么xml.jsp.jsf.js等等,我们没有必要全部都去自动校验一下,只是需要的时候才会手工校验一下! 取消方法: windows–>perferences–>myeclipse–>validation 除开Manual下面的复选框全部选中之外,其他全部不选 手工验证方法: 在要验证的文件上,单

  • Spring MVC的文件下载实例详解

    Spring MVC的文件下载实例详解 读取文件 要下载文件,首先是将文件内容读取进来,使用字节数组存储起来,这里使用spring里面的工具类实现 import org.springframework.util.FileCopyUtils; public byte[] downloadFile(String fileName) { byte[] res = new byte[0]; try { File file = new File(BACKUP_FILE_PATH, fileName); i

随机推荐