如何在Spring中使用编码方式动态配置Bean详解
作者:deniro
bean与spring容器的关系
Bean配置信息定义了Bean的实现及依赖关系,Spring容器根据各种形式的Bean配置信息在容器内部建立Bean定义注册表,然后根据注册表加载、实例化Bean,并建立Bean和Bean的依赖关系,最后将这些准备就绪的Bean放到Bean缓存池中,以供外层的应用程序进行调用。
本文将给大家详细介绍关于在Spring中使用编码方式动态配置Bean的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。
1 DefaultListableBeanFactory
DefaultListableBeanFactory 实现了 ConfigurableListableBeanFactory 接口,可以通过这个类来动态注入 Bean。为了保证注入的 Bean 也能被 AOP 增强,我们需要实现 Bean 的工厂后置处理器接口 BeanFactoryPostProcessor。
需要动态注入的 Bean:
public class BookService { BookDao bookDao; public void setBookDao(BookDao bookDao) { this.bookDao = bookDao; } public BookDao getBookDao() { return bookDao; } }
实现 Bean 的工厂后置处理器接口:
@Component public class BookServiceFactoryBean implements BeanFactoryPostProcessor { public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { DefaultListableBeanFactory factory = (DefaultListableBeanFactory) beanFactory; //Bean 定义 BeanDefinitionBuilder builder=BeanDefinitionBuilder.genericBeanDefinition (BookService.class); //设置属性 builder.addPropertyReference("bookDao","bookDao"); //注册 Bean 定义 factory.registerBeanDefinition("bookService1",builder.getRawBeanDefinition()); //注册 Bean 实例 factory.registerSingleton("bookService2",new net.deniro.spring4.dynamic.BookService()); } }
这里假设 bookDao 已注入容器(XML 或 注解方式)。
在此,我们既可以注册 Bean 的定义,也可以直接注册 Bean 的实例。
配置:
<context:component-scan base-package="net.deniro.spring4.dynamic" />
单元测试:
BookService bookService1 = (BookService) context.getBean("bookService1"); assertNotNull(bookService1); assertNotNull(bookService1.getBookDao()); BookService bookService2 = (BookService) context.getBean("bookService2"); assertNotNull(bookService2);
2 自定义标签
为了更好地封装组件,增强组件的易用性,我们会将组件定义为标签。
自定义标签步骤为:
- 采用 XSD 描述自定义标签的元素属性。
- 编写 Bean 定义的解析器。
- 注册自定义标签的解析器。
- 绑定命名空间解析器。
在 resources 中的 schema 文件夹下创建 bookservice.xsd
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns="http://www.deniro.net/schema/service" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans" targetNamespace="http://www.deniro.net/schema/service" elementFormDefault="qualified" attributeFormDefault="unqualified" > <!-- 导入 beans 命名空间--> <xsd:import namespace="http://www.springframework.org/schema/beans"/> <!-- 定义 book-service 标签--> <xsd:element name="book-service"> <xsd:complexType> <xsd:complexContent> <xsd:extension base="beans:identifiedType"> <!-- 定义 dao 属性--> <xsd:attribute name="dao" type="xsd:string" use="required"/> </xsd:extension> </xsd:complexContent> </xsd:complexType> </xsd:element> </xsd:schema>
接着定义服务标签解析器:
public class BookServiceDefinitionParser implements BeanDefinitionParser { public BeanDefinition parse(Element element, ParserContext parserContext) { //创建 Bean 定义 BeanDefinitionBuilder builder=BeanDefinitionBuilder.genericBeanDefinition (BookService.class); //注入自定义的标签属性 String dao=element.getAttribute("dao"); builder.addPropertyReference("bookDao",dao); //注册 Bean 定义 parserContext.registerBeanComponent(new BeanComponentDefinition(builder .getRawBeanDefinition(),"bookService")); return null; } }
然后把刚刚定义好的解析器注册到命名空间:
public class BookServiceNamespaceHandler extends NamespaceHandlerSupport { public void init() { registerBeanDefinitionParser("book-service",new BookServiceDefinitionParser()); } }
接着在 resources 中创建 META-INF 文件夹,并新建 spring.schemas 与 spring.handlers,这两个文件分别用于配置自定义标签的文档结构文件路径以及解析自定义命名空间的解析器。
文件路径
spring.handlers:
http\://www.deniro.net/schema/service=net.deniro.spring4.dynamic.BookServiceNamespaceHandler
spring.schemas:
http\://www.deniro.net/schema/service.xsd=schema/bookservice.xsd
注意: xsd 文件必须放在 resources 的子孙目录下。
引用自定义标签:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:me="http://www.deniro.net/schema/service" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.deniro.net/schema/service http://www.deniro.net/schema/service.xsd "> <bean id="bookDao" class="net.deniro.spring4.dynamic.BookDao"/> <me:book-service dao="bookDao"/> </beans>
这里,我们在头部引用了自定义标签,并命名为 “me”,然后就可以使用它咯O(∩_∩)O~
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。