Spring5参考指南:容器扩展
文章目录
- BeanPostProcessor自定义bean
- BeanFactoryPostProcessor自定义配置元数据
- 使用FactoryBean自定义实例化逻辑
Spring提供了一系列的接口来提供对Spring容器的扩展功能。下面我们一一介绍。
BeanPostProcessor自定义bean
前面一篇文章我们在自定义bean中提到,可以实现Spring的InitializingBean和DisposableBean接口来实现自定义bean的生命周期。如果是容器级别的,Spring提供了更加强大的BeanPostProcessor,来实现在容器级对Bean的扩展。
BeanPostProcessor接口定义了两个方法:
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}
该方法在调用容器初始化方法(如InitializingBean.afterPropertiesSet()或任何声明的init方法)之前,以及在任何bean初始化之后,被调用。
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;}
该方法在容器初始化方法之后被调用。
BeanPostProcessor可以配置多个,如果想控制多个BeanPostProcessor的顺序,可以实现Ordered接口,来定义他们的顺序。
虽然BeanPostProcessor是通过ApplicationContext自动检测的,你也可通过ConfigurableBeanFactory的addBeanPostProcessor来手动注册。手动注册则其Ordered失效,以手动注册的先后为准。
还要注意,以编程方式注册的BeanPostProcessor实例总是在注册为自动检测的实例之前进行处理,而不接收任何显式排序。
所有BeanPostProcessor实例和这些实例直接引用的bean都在启动时实例化,因为AOP自动代理是作为BeanPostProcessor本身实现的,所以BeanPostProcessor实例和它们直接引用的bean都不符合自动代理的条件。
下面是一个调用的例子:
<bean id="beanA" class="com.flydean.beans.BeanA"/><bean id="beanB" class="com.flydean.beans.BeanB"/><bean class="com.flydean.beans.InstantiationTracingBeanPostProcessor"/>
调用实现:
public static void main(final String[] args) throws Exception {ApplicationContext ctx = new ClassPathXmlApplicationContext("bean-post-processor.xml");BeanA beanA = (BeanA) ctx.getBean("beanA");System.out.println(beanA);}
BeanFactoryPostProcessor自定义配置元数据
BeanFactoryPostProcessor接口的语义与BeanPostProcessor的语义相似,但有一个主要区别:BeanFactoryPostProcessor对Bean配置元数据进行操作。也就是说,Spring IOC容器允许BeanFactoryPostProcessor读取配置元数据,并可能在容器实例化BeanFactoryPostProcessor实例以外的任何bean之前对其进行更改。
BeanFactoryPostProcessor也可以配置多个,并通过实现Ordered接口来确定执行顺序。BeanFactoryPostProcessor定义了一个方法:
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
通过该方法可以获取到可配置的beanFactory从而对bean定义进行修改。
Spring提供了很多预定义的bean工厂后处理器,例如PropertyOverrideConfigurer和PropertyPlaceholderConfigurer。下面我们通过例子来说明怎么使用。
PropertyOverrideConfigurer类名替换
PropertyPlaceholderConfigurer主要用于从外部的Property文件读取属性,用来替换定义好的配置,这样做可以使部署应用程序的人员自定义特定于环境的属性,如数据库URL和密码,而不必为容器修改一个或多个XML定义主文件从而增加复杂性或风险。
下面是配置的XML文件:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"><property name="locations" value="classpath:jdbc.properties"/></bean><bean id="dataSource" destroy-method="close"class="com.flydean.beans.BasicDataSource"><property name="driverClassName" value="${jdbc.driverClassName}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></bean>
这个例子展示了属性被配置在外部的Properties文件中。在运行时,使用PropertyPlaceholderConfigurer将元数据替换成DataSource中的某些属性。要替换的值被指定为${property-name}格式的占位符,该格式遵循ant和log4j以及JSP EL样式。
真实的值取自外部的Java Properties格式的文件:
jdbc.driverClassName=org.hsqldb.jdbcDriver
jdbc.url=jdbc:hsqldb:hsql://production:9002
jdbc.username=sa
jdbc.password=root
PropertyOverrideConfigurer属性覆盖
PropertyOverrideConfigurer可以用来覆盖Bean属性的默认值,或者设置新的值。我们看一个例子:
<bean class="org.springframework.beans.factory.config.PropertyOverrideConfigurer"><property name="locations" value="classpath:override.properties"/><property name="properties"><value>beanOverride.url=com.something.DefaultStrategy</value></property></bean><bean name="beanOverride" class="com.flydean.beans.BeanOverride"/>
对应的类是:
@Data
public class BeanOverride {private String name="beanA";private String url="http://www.163.com";}
它的默认属性会被覆盖。
使用FactoryBean自定义实例化逻辑
FactoryBean接口提供3个方法:
- Object getObject(): 返回工厂创建的实例,该实例可能是被共享的, 取决于该实例是单例还是多例模式。
- boolean isSingleton():判断FactoryBean返回的是单例还是多例。
- Class getObjectType():返回getObject() 方法返回的类型,如果提前不知道类型,那么返回null。
我们可以实现FactoryBean接口来自定义Bean的实现逻辑。
public class BeanFactoryBean implements FactoryBean {@Resourceprivate BeanA beanA;@Overridepublic Object getObject() throws Exception {return beanA;}@Overridepublic Class<?> getObjectType() {return BeanA.class;}
}
下面是其配置:
<context:annotation-config/><bean id="beanA" class="com.flydean.beans.BeanA"/><bean id="beanFactoryBean" class="com.flydean.beans.BeanFactoryBean"/>
如何使用?
public static void main(final String[] args) throws Exception {ApplicationContext ctx = new ClassPathXmlApplicationContext("bean-factory.xml");BeanFactoryBean beanFactoryBean = (BeanFactoryBean) ctx.getBean("&beanFactoryBean");System.out.println(beanFactoryBean.getObject());System.out.println(beanFactoryBean.getObjectType());BeanA beanA=(BeanA)ctx.getBean("beanFactoryBean");System.out.println(beanA);}
当需要向容器请求实际的FactoryBean实例本身而不是它生成的bean时,在调用ApplicationContext的getbean()方法时,在bean的ID前面加上符号(&)。因此,对于ID为beanFactoryBean的给定FactoryBean,在容器上调用getBean(“beanFactoryBean”)返回FactoryBean生成的bean,而调用getBean(“&beanFactoryBean”)则返回FactoryBean实例本身。
本节的例子可以参考:ioc-extend
更多精彩内容且看:
- 区块链从入门到放弃系列教程-涵盖密码学,超级账本,以太坊,Libra,比特币等持续更新
- Spring Boot 2.X系列教程:七天从无到有掌握Spring Boot-持续更新
- Spring 5.X系列教程:满足你对Spring5的一切想象-持续更新
- java程序员从小工到专家成神之路(2020版)-持续更新中,附详细文章教程
更多教程请参考flydean的博客
Spring5参考指南:容器扩展相关推荐
- Spring5参考指南:IOC容器
文章目录 为什么使用Spring5 什么是IOC容器 配置元数据 实例化容器 XML嵌套 groovy bean定义DSL 使用容器 最近在翻译Spring Framework Documentati ...
- Spring5参考指南:基于注解的容器配置
文章目录 @Required @Autowired @primary @Qualifier 泛型 @Resource @PostConstruct和@PreDestroy Spring的容器配置可以有 ...
- Spring5参考指南:事件Event
文章目录 基于继承的Event 基于注解的Event 异步侦听器 Spring提供了很方便的事件的处理机制,包括事件类ApplicationEvent和事件监听类ApplicationListener ...
- Spring5参考指南:组件扫描
文章目录 组件扫描 @Component 元注解和组合注解 组件内部定义Bean元数据 为自动检测组件命名 为自动检测的组件提供作用域 生成候选组件的索引 组件扫描 上一篇文章我们讲到了annotat ...
- Spring5参考指南: SpEL
文章目录 Bean定义中的使用 求值 支持的功能 函数 Bean引用 If-Then-Else Elvis Safe Navigation 运算符 集合选择 集合投影 表达式模板化 SpEL的全称叫做 ...
- Spring5参考指南: BeanWrapper和PropertyEditor
文章目录 BeanWrapper PropertyEditor BeanWrapper 通常来说一个Bean包含一个默认的无参构造函数,和属性的get,set方法. org.springframewo ...
- Spring5参考指南:Environment
文章目录 Profiles PropertySource 使用@PropertySource Spring的Environment接口有两个关键的作用:1. Profile, 2.properties ...
- Spring5参考指南:Bean的生命周期管理
文章目录 Spring Bean 的生命周期回调 总结生命周期机制 startup和Shutdown回调 优雅的关闭Spring IoC容器 Spring Bean 的生命周期回调 Spring中的B ...
- Spring5参考指南:Bean作用域
文章目录 Bean作用域简介 Singleton作用域 Prototype作用域 Singleton Beans 中依赖 Prototype-bean web 作用域 Request scope Se ...
最新文章
- jQuery元素内容操作的方法有多少种?
- php面试题之五——MySQL数据库(基础部分)
- 刚盈利的DeepMind收购MuJoCo:转手开源,所有人免费用
- python3.5中文手册_Python 入门指南 — Python3 中文手册 3.5.2 文档 | 三维部落
- 天津2021年高考成绩查询入口,2021年天津高考成绩查询时间安排 什么时候出分
- 面试题:如何实现一个深拷贝
- iOS 关于真机和模拟器framework合并
- 数据结构思维 第四章 `LinkedList`
- Java 的数据类型示意图
- MySQL-5.6.x二进制版本安装记录
- 有效的python属性管理:描述符的使用
- pd虚拟机专用windows系统镜像(m1/intel)「新增:Intel Mac win7专业版懒人包镜像」
- ubuntu安装nessus
- 【Unity游戏开发】动画系统(二)2D动画
- 弘辽科技:拼多多怎么提升访客量?有哪些方法?
- OAuth2学习(一)——初识OAuth2
- 从零开始的Nginx详解(3)【Nginx-Https服务配置详解】
- NB-Iot烟感03:感烟探测器原理图设计
- ARCore之路-技术原理(一)
- 浙江临海一民警收到“红牌警告”:立即停止工作