把对象交给spring管理的3种方法及经典应用
背景
先说一说什么叫把对象交给spring管理。它区别于把类交给spring管理。在spring里采用注解方式@Service、@Component这些,实际上管理的是类,把这些类交给spring来负责实例化。
而对象交给spring管理,举个例子,最常见的在配置文件里定义一个bean,或者JavaConfig的方式就是在@Configure标签标注的类里的@Bean对象。这些Bean已经new出来了。是以对象实例的方式交给spring管理的。这些对象往往是与业务无关的基础组件。比如datasource的bean、redis连接池的bean。个数是有限的。
特别是面试的时候千万要注意他们的区别。有时候有的人觉得自己回答没问题,最后面试没通过,很可能是因为没有弄清楚面试的考察点。面试官的逻辑是如果你没弄清楚问题就回答,面试官很可能会怀疑工作中接到任务也会没有弄清楚就直接开干,做出些负产出来。建议面试的时候不但回答问题,同时也可以说对象交给spring管理和类交给spring管理有点类似,但是……这样清楚的表达自己的思考。
方法一:XML配置Bean
这个方法非常常见,举个例子:
<bean id="car" class="com.lm.spring.bean.Car">
这种定义方法相当于Car car = new Car() 然后 注册car到spring容器。用的时候直接用。
既然bean是被实例化后的对象,就涉及到对象实例化的时候要传参数的问题。
<bean id="car" class="com.lm.spring.bean.Car"><constructor-arg value="Baoma"></constructor-arg><constructor-arg value="Red"></constructor-arg><constructor-arg value="400000"></constructor-arg></bean>
这是构造器传参方式,相当于
Car car = new Car("Baoma","Red","400000")。当然构造器传参还支持指定参数的index或者name啥的。其中value代表是基本数据类型,也可以传对象,对象用ref=,代表传的是另外一个bean.
经典的配置场景是数据库配置:先配置dataSource,再配置需要引用dataSource的sessionFactory。
<!-- 数据源配置 --><bean id="ds" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"><!-- 基本属性 url、user、password --><property name="url" value="#{props.url}" /><property name="username" value="#{props.user}" /><property name="password" value="#{props.password}" /><!-- 配置初始化大小、最小、最大 --><property name="initialSize" value="#{props.initialPoolSize}" /><property name="minIdle" value="#{props.minPoolSize}" /><property name="maxActive" value="#{props.maxPoolSize}" /><!-- 配置获取连接等待超时的时间 --><property name="maxWait" value="#{props.maxIdleTime}" /><!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 --><property name="timeBetweenEvictionRunsMillis" value="#{props.timeBetweenEvictionRunsMillis}" /><!-- 配置一个连接在池中最小生存的时间,单位是毫秒 --><property name="minEvictableIdleTimeMillis" value="#{props.minEvictableIdleTimeMillis}" /><!-- 打开PSCache,并且指定每个连接上PSCache的大小 --><property name="poolPreparedStatements" value="true" /><property name="maxPoolPreparedStatementPerConnectionSize" value="20" /></bean><!-- sessionFactory --><bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"><property name="dataSource" ref="ds"></property><!-- <property name="hibernateProperties"></property> --><property name="configLocation" value="classpath:com/chinasofti/etc/conf/hibernate.cfg.xml"></property></bean>
这些都是常规用法。前段时间见到了另外一种用法,虽然没啥技术难度。确实之前没有这么用过,也觉得很有意思:
<bean id="car" class="java.util.ArrayList"><property name="cars"><list><ref bean="car1"></ref><ref bean="car2"></ref><ref bean="car3"></ref></list></property></bean>
这里用property方法传参相当于调用set方法传参。当然,这里除了可以定义ArrayList对象,还可以定义HashMap、HashSet、Array。
我看到这个恍然大悟,原来自己写的一些方法都不地道。比如机房信息,一个公司可能有七八个机房,什么大兴机房、永丰机房啥的。这个内容很少,放在数据库里没啥必要,之前项目就直接在程序里用枚举定义出来,然后放到map里的。如果加了个机房,就改改代码上线呗。
其实更合适的方法,应该是在配置文件里定义一个class="java.util.map"的bean。然后把内容都放到配置文件里。这些每次添加机房,只改配置文件,不改代码,更合理一些。
虽然实际来讲哈,现在都走devops工具发布了,成本工作量是一样的。但是这样写,能明确修改的是配置,不是代码逻辑。影响范围会更明确些。
方法二:@Bean
这个方法是spring boot流行后的常用方法。本质和XML配置方法相同。所有用XML配置文件的方法都可以用这个方法改写。
@Configuration //此处为配置项public class ServiceConfig {@Bean //此处返回的是一个Spring的配置Bean,与xml的<bean>等价public IMessageService getMessageService() {//方法名称随便写return new MessgeServiceImpl();}}
很多基础组件的使用文档提供的是XML配置形式的,看到过一些刚毕业的同学在抓耳挠腮。因为项目用的spring boot。如果了解他们的本质就会知道可以直接自己这样写。
方法三:BeanFacoty registerSingleton
先上代码,定义一个普通Bean。
@Data
public class User {
private Integer id;
private String name;
private String password;
private Integer age;
}
定义一个被spring可以扫描的类,这个类要实现
BeanFactoryPostProcessor。里面调用registerSingleton注册一个对象。
@Component
public class MyBeanFacoty implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
User user1 = new User();
user1.setId(1);
user1.setName("贾元春");
user1.setAge(27);
configurableListableBeanFactory.registerSingleton("user", user1);
}
}
之后就可以随时进行依赖了。
@RestController
public class JacksonController {
@Resource
private User user;
@GetMapping("/writeStringAsString")
public String writeStringAsString(String toWrite) throws Exception {
System.out.println(user.getAge());
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.writeValueAsString(toWrite);
}
这时候大家是否会有个疑问,XML配置Bean是传统的spring mvc里常用的将对象交给spring来管理的方法,@Bean是spring boot里将对象交给spring来管理的方法。那为什么还要有这个先实现BeanFactoryPostProcessor的方法呢?
因为这种方法可以用来做这件事情,但是不仅仅可以做这件事情。它神通广大,不仅可以将一个对象交给spring管理,还可以将已经交给spring管理的对象拿出来进行修改,还有其他各种的spring初始化的干预都可以做。所以用它来仅仅注册一个Bean有点杀鸡用牛刀的味道。
总结思考
之前也写过一些spring的文章,如:
SpringBoot启动原理
学习Spring的思考框架
专治不会看源码的毛病--spring源码解析AOP篇(2017版)
SpringBoot优雅退出
你看不懂的spring原理是因为不知道这几个概念
Spring参数的自解析--还在自己转换?你out了!
这些文章主要围绕的核心就是spring framework的原理和spring看似基础的应用技巧。
这是我的一个理念。学spring和学厨师很像。基础就是刀工、材料和火候。掌握了基础,通过自己的悟性就可以千变万化了。悟性不是靠教的,有用的还是基础。
spring有很多的扩展内容,spring boot、spring cloud、spring batch。之所以有这些就是因为它做了两件事:第一是控制反转,使用Bean的时候随时取用;第二是aop,把那些可以重用的代码写一份想用的地方都可以生效。
刚毕业的时候,有大师教我们说控制反转和依赖注入是一回事,后来我想想其实不是。控制反转是把对象和类交给spring来管理,由spring来控制器生命周期的过程。依赖注入是在使用对象的时候,可以通过set、构造器和注解方式获取对象的过程。一个是存钱的过程,一个是取钱的过程。联系是存钱是为取钱服务的。
而spring的一些高级框架就是将更多的东西交给spring来管理的过程,比如spring-jdbc,就是通过spring容器就可以调用jdbc了。我个人认为原理了解了,学的价值不大。
spring作者是学音乐出身的。spring牛的地方是它的理念,它没有做什么事情,只是把能替程序员做的事情都做了,给程序员开发带来了春天。把开发变成了艺术。
把对象交给spring管理的3种方法及经典应用的更多相关文章
- Spring管理事物两种方式
Spring管理事物两种方式 1. 编程式事物管理(在开发中不经常使用) 使用步骤 1. 配置数据库事物管理 DataSourceTransactionManager <!--配置事物管理器-- ...
- 使用Spring Security3的四种方法概述
使用Spring Security3的四种方法概述 那么在Spring Security3的使用中,有4种方法: 一种是全部利用配置文件,将用户.权限.资源(url)硬编码在xml文件中,已经实现过, ...
- javascript获取json对象的key名称的两种方法
javascript获取json对象的key名称的两种方法 数据处理中,你可能接收到一个不确定内容格式的json对象,然后要把key的值提取出来.今天试过两种可以提取json key的方法,均可以正常 ...
- js对象之间的"继承"的五种方法
今天要介绍的是,对象之间的"继承"的五种方法. 比如,现在有一个"动物"对象的构造函数. function Animal(){ this.species = & ...
- strut1.X和spring整合的二种方法
第一种集成方法 原理:在Action中取得BeanFactory对象,然后通过BeanFactory获取业务逻辑对象 缺点:产生了依赖,spring的类在action中产生了依赖查找.(注意和依赖注入 ...
- Spring实例化Bean三种方法:构造器、静态工厂、实例工厂
Spring中Bean相当于java中的类,可以通过xml文件对bean进行配置和管理. 一.Bean的实例化: 构造器实例化.静态工厂实例化.实例工厂方式实例化. 目录: 构造器实例化: xml配置 ...
- Spring创建对象的几种方法
一.通过构造器 无参构造器 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=" ...
- js中控制流管理的四种方法
引自http://es6.ruanyifeng.com/#docs/generator#yield--表达式 1.常用的回调方法 step1(function (value1) { step2(val ...
- java对象转换String类型的三种方法
在很多情况下我们都需要将一个对象转换为String类型.一般来说有三种方法可以实现:Object.toString().(String)Object.String.valueOf(Object).下面 ...
随机推荐
- js代码 简单实现数字滚动增加动效(原)
<html><body> <span>look this:</span><span id="nums">10000< ...
- buu Youngter-drive
一.查壳,发现是upx的壳,用自解压方式,脱下壳 二.之后发现打不开了,应该是要修复,不想修复了,直接拖入ida 找到关键函数,中间发生一点小插曲,发现堆栈不平衡,然后导致F5反编译失败,百度了下是A ...
- runtime使用总结
runtime这个东西,项目是很少用到的,但面试又避不可少,了解其内部的机制对底层的理解还是很有必要的. 1.动态添加属性 拓展类别属性的简单实现 a.定义字面量指针 static char dyna ...
- 阿里云低延时直播 RTS 能力升级 让直播推流效果更佳
行业背景 直播技术飞速发展让各个行业的用户体验呈现多样化和个性化,不同业务场景下创新实践满足大众对于音视频互动体验和参与的高标准要求.历经2020年初的巨变之后,以视频.游戏.电商.教育为主的互联网经 ...
- Min25 筛学习笔记
仅仅是 \(min25\) 筛最基本的方法,没有任何推式子的例题.(想了想还是加两道吧qwq) 这里解决的是 \(Luogu\) 那道模板题. min25 基本方法: 最基础的是两个式子: \[G(n ...
- 「AGC035C」 Skolem XOR Tree
「AGC035C」 Skolem XOR Tree 感觉有那么一点点上道了? 首先对于一个 \(n\),若 \(n\equiv 3 \pmod 4\),我们很快能够构造出一个合法解如 \(n,n-1, ...
- SSM框架,在Html界面利用ajax,json,jQuery实现省市区下拉框联动
1.先生成省市区表格 2.建立实体类 3.在html画出下拉框 <select id="province"> <option value="" ...
- post传参params与body的区别(@RequestParam和@RequestBody的区别)
1.axios post请求 Content-Type默认为 application/x-www-form-urlencoded,我们传递参数的时,params里面的参数(简单的对象,通过 &quo ...
- 总结开发中基于DevExpress的Winform界面效果
DevExpress是一家全球知名的控件开发公司, DevExpress 也特指此公司出品的控件集合或某系列控件或其中某控件.我们应用最为广泛的是基于Winform的DevExpress控件组,本篇随 ...
- 解决移动端在IOS中input输入框光标过长
在输入框样式中加入: line-height:20px;