(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无法进行注入,那到底是什 ...
随机推荐
- 题解报告:hdu 1285 确定比赛名次
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1285 Problem Description 有N个比赛队(1<=N<=500),编号依次 ...
- CSS------选择器-----------选择器的分组、属性选择器
/*!--选择器的分组--*/ .groupDiv h1,h2,h3,h4{ color: #000000; } /*------------------------属性选择器--*/ [title] ...
- Coursera公开课-Machine_learing:编程作业8(2016-10-06 20:49)
Anomaly Detection and Recommender Systems 本周编程作业分为两部分:异常检测和推荐系统. 异常检测:本质就是使用样本的到特种值的gaussian分布,来预估正确 ...
- 使用A*寻路小记
前几天做另一个DEMO 要用实现自动寻路功能,看到普遍都是A* 学习了下 我的主循环代码: isFindEndPoint = false; //主循环 do { CreateOutSkirtsNode ...
- 关于GIT使用过程中遇到的问题
npm构建,将所需要安装的依赖添加至package.json文件中,使用cnpm i进行安装 #拉去指定项目的默认分支: git pull http://username:password@gitla ...
- 研磨JavaScript系列
JavaScript是一种基于对象和事件驱动并具有相对安全性的客户端脚本语言.同时也是一种广泛用于客户端Web开发的脚本语言,常用来给HTML网页添加动态功能,比如响应用户的各种操作.它最初由网景公司 ...
- CSS基础知识(定位、浮动)
12.浮动 特点:将当前元素脱离文档流 float: left 即左浮动 float: right 即右浮动 注:*父与子元素,设置子元素浮动不能超出父元素的范围 *多个元素均设置为浮动时,将 ...
- [Windows Server 2012] 手工创建安全网站
★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com★ 护卫神·V课堂 是护卫神旗下专业提供服务器教学视频的网站,每周更新视频.★ 本节我们将带领大家:手工创建安全站 ...
- json 新用
如果使用struts2的action,可以省去属性赋值的工夫. 但是假如你没有使用struts2,而且使用的是ajax请求,通过json来传递参数.那我下面所说的对你可能是一个很好的解脱,从此告别re ...
- THREE.DecalGeometry(转载)
function getDecalGeometry(position, direction){ var decalGeometry = new THREE.DecalGeometry( earthMe ...