(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无法进行注入,那到底是什 ...
随机推荐
- 牛客小白月赛15 C 表单 ( map 使用)
链接:https://ac.nowcoder.com/acm/contest/917/C来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言52428 ...
- ibatis 基类生成
using IBatisNet.Common.Utilities; using IBatisNet.DataMapper; using IBatisNet.DataMapper.Configurati ...
- jQuery 事件 - trigger() 方法 和 triggerHandler() 方法
trigger() 方法触发被选元素的指定事件类型. triggerHandler() 方法触发被选元素的指定事件类型.但不会执行浏览器默认动作,也不会产生事件冒泡. triggerHandler() ...
- Linux 下 Solr的搭建与使用(建议jdk1.8以上)
官方表示solr5之后的版本不再提供对第三方容器的支持(不提供war包了). “旧式”solr.xml格式不再支持,核心必须使用core.properties文件定义. 使用第三方容器的需要自己手动修 ...
- 【Spring】AOP
AOP 编程允许你把遍布应用各处的功能分离出来形成可重用的组件,将安全.事务和日志关注点与你的核心业务逻辑相分离. 面向切面编程往往被定义为促使应用程序分离关注点的一项技术.系统由许多不同组件组成,每 ...
- 搭建本地wordpress
1.首先,下载xampp,安装按默认勾选即可. 2.安装完成后,启动Apache和MySQL这两个服务. 启动后变成绿色,表示启动成功. 3.点击MySQL项的Admin进入数据库后台. 4.点击用户 ...
- 笔记《精通css》第3章 盒模型,定位,浮动,清理
第3章 盒模型,定位,浮动,清理 1.盒模型用到的属性width,height,padding,border,margin 普通文档流的上下垂直margin会叠加 2.块级框 与 行内框, 利用 ...
- 【译】x86程序员手册08 -2.6中断和异常
2.6 Interrupts and Exceptions 中断和异常 The 80386 has two mechanisms for interrupting program execution: ...
- SSL&TLS传输层加密协议实现图解--(重要)
一.SSL&TLS 1.SSL:Secure Sockets Layer ,加密套接字协议层 1)SSL是为网络通信提供安全及数据完整性的一种安全协议,在传输层对网络连接进行加密 Secure ...
- UIResponder详解
UIResponder Class Reference Managing the Responder Chain 1.- (UIResponder *)nextResponder 返回接收者的下一个相 ...