(41)Spring Boot 使用Java代码创建Bean并注册到Spring中【从零开始学Spring Boot】
已经好久没有讲一些基础的知识了,这一小节来点简单的,这也是为下节的在Spring Boot中使用多数据源做准备。
从Spring 3.0开始,增加了一种新的途径来配置Bean Definition,这就是通过Java Code配置Bean Definition。
与XML和Annotation两种配置方式不同点在于:
前两种方式XML和Annotation的配置方式为预定义方式,即开发人员通过XML文件或者Annotation预定义配置Bean的各种属性后,启动Spring容器,Spring容器会首先解析这些配置属性,生成对应的Bean Definition,装入到DefaultListtableBeanFactory对象的属性容器中,以此同时,Spring框架也会定义内部使用的Bean定义,如Bean名为:org.springframework.context.annotation.internalConfigurationAnnotationProcessor”的 ConfigurationClassPostProcessor 定义。而后此刻不会做任何Bean Definition的解析动作,Spring框架会根据前两种配置,过滤出BeanDefinitionRegistryPostProcessor 类型的Bean定义,并通过Spring框架生成对应的Bean对象(如 ConfigurationClassPostProcessor 实例)。。结合 Spring 上下文源码可知这个对象是一个 processor 类型工具类,Spring 容器会在实例化开发人员所定义的 Bean 前先调用该 processor 的 postProcessBeanDefinitionRegistry(…) 方法。此处实现基于 Java Code 配置Bean Definition的处理。
基于 Java Code 的配置方式,其执行原理不同于前两种。它是在 Spring 框架已经解析了基于 XML 和 Annotation 配置后,通过加入 BeanDefinitionRegistryPostProcessor 类型的 processor 来处理配置信息,让开发人员通过 Java 编程方式定义一个 Java 对象。其优点在于可以将配置信息集中在一定数量的 Java 对象中,同时通过 Java 编程方式,比基于 Annotation 方式具有更高的灵活性。并且该配置方式给开发人员提供了一种非常好的范例来增加用户自定义的解析工具类。其主要缺点在于与 Java 代码结合紧密,配置信息的改变需要重新编译 Java 代码,另外这是一种新引入的解析方式,需要一定的学习成本。
提及一点的就是,Spring框架有3个主要的Hook类,分别是:
org.springframework.context.ApplicationContextAware
它的setApplicationContext 方法将在Spring启动之前第一个被调用。我们用来同时启动Jdon框架。
org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor
它的postProcessBeanDefinitionRegistry 和 postProcessBeanFactory 方法是第二和第三被调用,它们在Bean初始化创建之前启动,如果Spring的bean需要的其他第三方中的组件,我们在这里将其注入给Spring。
org.springframework.context.ApplicationListener
用于在初始化完成后做一些事情,当Spring所有XML或元注解的Bean都启动被创建成功了,这时会调用它的唯一方法onApplicationEvent。
下面我们来完成一个,自己通过java代码创建bean,并注册为Spring管理。
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->
本例中,我们创建一个接口,然后创建该接口的2个实现类,分别命名不同的名字,然后在需要注入的地方使用@Qualifier 指定注入对应的实例。
接口com.kfit.demo.Shanhy.java
package com.kfit.demo;
publicinterface Shanhy {
publicvoid dispaly();
}
实现类com.kfit.demo.ShanhyA.java
package com.kfit.demo;
publicclass ShanhyA implements Shanhy{
@Override
publicvoid dispaly() {
System.out.println("ShanhyA.dispaly()");
}
}
实现类com.kfit.ShanhyB.java
package com.kfit.demo;
publicclass ShanhyB implements Shanhy {
@Override
publicvoid dispaly() {
System.out.println("ShanhyB.dispaly()");
}
}
定义接口BeanDefinitionRegistryPostProcessor的实现:
com.kfit.config.MyBeanDefinitionRegistryPostProcessor:
package com.kfit.config;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.Configuration;
import com.kfit.demo.ShanhyA;
import com.kfit.demo.ShanhyB;
/**
* 实现自己实例化bean并注册为Spring管理
* @author Angel(QQ:412887952)
* @version v.0.1
*/
@Configuration
publicclass MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
//bean 的名称生成器.
private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
@Override
publicvoid postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("MyBeanDefinitionRegistryPostProcessor.postProcessBeanFactory()");
}
/**
* 先执行:postProcessBeanDefinitionRegistry()方法,
* 在执行:postProcessBeanFactory()方法。
*
*/
@Override
publicvoid postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("MyBeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry()");
/*
* 在这里可以注入bean.
*/
registerBean(registry, "shanyA", ShanhyA.class);
registerBean(registry, "shanyB", ShanhyB.class);
}
/**
* 提供公共的注册方法。
* @param beanDefinitionRegistry
* @param name
* @param beanClass
*/
privatevoid registerBean(BeanDefinitionRegistry registry,String name,Class<?> beanClass){
AnnotatedBeanDefinition annotatedBeanDefinition = new AnnotatedGenericBeanDefinition(beanClass);
//可以自动生成name
String beanName = (name != null?name:this.beanNameGenerator.generateBeanName(annotatedBeanDefinition, registry));
//bean注册的holer类.
BeanDefinitionHolder beanDefinitionHolder = new BeanDefinitionHolder(annotatedBeanDefinition, beanName);
//使用bean注册工具类进行注册.
BeanDefinitionReaderUtils.registerBeanDefinition(beanDefinitionHolder, registry);
}
}
这个类里的代码比较多,在这里简单的介绍下:方法postProcessBeanDefinitionRegistry()是用来注册bean的;而具体注册的代码比较是通用的,我们定义一个私有的方法进行注册。
postProcessBeanFactory()是bean配置的工厂方法,在这个方法中可以获取到我们所有在postProcessBeanDefinitionRegistry方法中注册的所有bean,在这里我们可以进行属性的设置等操作。
// 这里可以设置属性,例如
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("dataSourceA");
MutablePropertyValues mutablePropertyValues = beanDefinition.getPropertyValues();
//加入属性.
mutablePropertyValues.addPropertyValue("driverClassName", "com.mysql.jdbc.Driver");
mutablePropertyValues.addPropertyValue("url", "jdbc:mysql://localhost:3306/test");
mutablePropertyValues.addPropertyValue("username", "root");
mutablePropertyValues.addPropertyValue("password", "123456");
测试代码:
以直接注入我们的对象,对于同样接口的我们需要指定name:
package com.kfit.config;
import org.kfit.service.HelloService;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.kfit.demo.Shanhy;
@Configuration
publicclass MyConfig {
/**
* 这里只是测试使用,没有实际的意义.
*/
@Bean(name="testHelloService")
public HelloService filterRegistrationBean(@Qualifier("shanhyB") Shanhy shanhy){
HelloService helloService = new HelloService();
shanhy.display();
// 其它处理代码.
returnhelloService;
}
}
使用@Resource 或者 @Autowired并指定@Qualifier 也可以:
package com.kfit.controller;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.kfit.demo.Shanhy;
/**
*
* @author Angel(QQ:412887952)
* @version v.0.1
*/
@RestController
publicclass HelloController {
@Resource(name = "shanhyA")
private Shanhy shanhyA;
@Autowired
@Qualifier("shanhyB")
private Shanhy shanhyB;
@RequestMapping("/test")
public String test(){
shanhyA.display();
shanhyB.display();
return"test";
}
}
访问:http://127.0.0.1:8080/test 查看控制台的打印信息。
在源代码中由于代码有此系列教程别的章节的代码,请自行忽略阅读,给大家造成的不变请谅解。
【Spring Boot 系列博客】
0)前言【从零开始学Spring Boot】 :
http://412887952-qq-com.iteye.com/blog/2291496
(1)spring boot起步之Hello World【从零开始学Spring Boot】:
http://412887952-qq-com.iteye.com/blog/2291500
(2)Spring Boot返回json数据【从零开始学Spring Boot】
http://412887952-qq-com.iteye.com/blog/2291508
(15)Spring Boot使用Druid和监控配置【从零开始学Spring Boot】
http://412887952-qq-com.iteye.com/blog/2292362
16)Spring Boot使用Druid(编程注入)【从零开始学Spring Boot】
http://412887952-qq-com.iteye.com/blogs/2292376
(17)Spring Boot普通类调用bean【从零开始学Spring Boot】:
http://412887952-qq-com.iteye.com/blog/2292388
......
(35)Spring Boot集成Redis实现缓存机制【从零开始学Spring Boot】
(41)Spring Boot 使用Java代码创建Bean并注册到Spring中【从零开始学Spring Boot】的更多相关文章
- Spring Boot 使用Java代码创建Bean并注册到Spring中
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/catoop/article/details/50558333 声明同一个类下的多个实例: packa ...
- 21.Spring Boot 使用Java代码创建Bean并注册到Spring中
转自:https://blog.csdn.net/catoop/article/details/50558333
- Spring Boot 使用Java代码创建Bean并注冊到Spring中
从 Spring3.0 開始,添加了一种新的途经来配置Bean Definition,这就是通过 Java Code 配置 Bean Definition. 与Xml和Annotation两种配置方式 ...
- Spring实战——通过Java代码装配bean
上篇说的是无需半行xml配置完成bean的自动化注入.这篇仍然不要任何xml配置,通过Java代码也能达到同样的效果. 这么说,是要把上篇的料拿出来再煮一遍? 当然不是,上篇我们几乎都在用注解的方式如 ...
- Spring 之通过 Java 代码装配 bean
[关于IoC的几点认识] 1.面向接口编程 --> 每层只向上层提供接口 2.inversion of control (IoC) -->参考百度百科 3.DI是IoC的一种实现方式 [ ...
- Spring装配之——JAVA代码装配Bean
首先创建几个普通的JAVA对象,用于测试JAVA代码装配bean的功能. package soundsystemJava; //作为接口 定义了CD播放器对一盘CD所能进行的操作 public int ...
- (29)Spring boot 文件上传(多文件上传)【从零开始学Spring Boot】
文件上传主要分以下几个步骤: (1)新建maven java project: (2)在pom.xml加入相应依赖: (3)新建一个表单页面(这里使用thymleaf); (4)编写controlle ...
- 17、Spring Boot普通类调用bean【从零开始学Spring Boot】
转载:http://blog.csdn.net/linxingliang/article/details/52013017 我们知道如果我们要在一个类使用spring提供的bean对象,我们需要把这个 ...
- 70.打印所有Spring boot载入的bean【从零开始学Spring Boot】
[从零开始学习Spirng Boot-常见异常汇总] 问题的提出: 我们在开发过程当中,我们可能会碰到这样的问题:No qualifying bean 就是我们定义的bean无法进行注入,那到底是什 ...
随机推荐
- CSS里面position:relative与position:absolute 区别
position:absolute这个是绝对定位:是相对于浏览器的定位.比如:position:absolute:left:20px;top:80px; 这个容器始终位于距离浏览器左20px,距离浏览 ...
- openstack 虚拟机导出
- Angular.forEach用法总结
}; }]; var so=[]; var so2=[]; var so3=[]; var so4=[]; var so5=[]; var so6=[]; ; ; angular.forEach(so ...
- MySQL 1071错误解决办法
今天在使用mysql时,又遇到了如博文标题所示的问题,以前针对该问题未进行记录,今天特意进行说明存档. 该问题是由键值字段长度过长导致.mysql支持数据库表单一键值的最大长度不能超过 ...
- [Swift通天遁地]三、手势与图表-(1)监听屏幕上触摸事件的各种状态
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- MySQL索引失效及使用索引的优缺点
本文所有实验基于MySQL5.7.21,实验将会用到Explain工具,不了解的同学可参考此文章:MySQL性能优化神器Explain详解 联合索引失效 先创建一个包含三个字段的联合索引,索引顺序如下 ...
- [转]我是蒟蒻,但我有我的OI信仰
我想最大的浪漫莫过于有人陪你征战OI吧 有多少无眠的夜晚?我总是在想, 到底是为了什么? 为了自招?为了省队?为了签约? 这条路很艰难,不可谓不凶险, 当你第一次踏上复试, 你肯定有看到过那些很厉害很 ...
- 命令框中oracle dmp文件的导入和导出(仅做个人备忘)
1.dmp文件导出 (全部)exp 用户名/密码 rows=y indexes=n compress=n buffer=65536 feedback=100000 file=F:\test.dmp ...
- 345 Reverse Vowels of a String 反转字符串中的元音字母
编写一个函数,以字符串作为输入,反转该字符串中的元音字母.示例 1:给定 s = "hello", 返回 "holle".示例 2:给定 s = "l ...
- 开始玩qt,使用代码修改设计模式生成的菜单
之前制作菜单时,不是纯代码便是用设计模式 直接图形化完成. 今天我就是想用代码修改已经存在的菜单项,如果是用代码生成的可以直接调用指针完成: 但通过设计模式完成的没有暴露指针给我,至少我没发现. 在几 ...