文档章节

【62】Spring总结之bean(3)

fengsehng
 fengsehng
发布于 2016/11/09 09:15
字数 2430
阅读 1
收藏 0
点赞 0
评论 0

Spring核心机制:依赖注入

Java应用(从applets的小范围到全套n层服务端企业应用)是一种典型的依赖型应用,它就是由一些互相适当地协作的对象构成的。因此,我们说这些对象间存在依赖关系。加入A组件调用了B组件的方法,我们就可以称A组件依赖于B组件。我们通过使用依赖注入,Java EE应用中的各种组件不需要以硬编码方式耦合在一起,甚至无需使用工厂模式。当某个Java 实例需要其他Java 实例时,系统自动提供所需要的实例,无需程序显示获取,这种自动提供java实例我们谓之为依赖注入,也可以称之为控制反转(Inversion of Control IoC)。

依赖注入通常有如下两种:

设置注入:IoC容器使用属性的setter方法来注入被依赖的实例。
构造注入:IoC容器使用构造器来注入被依赖的实例。

设值注入


2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <!-- 配置Chinese实例,其实现类是Chinese -->
    <bean id="chinese" class="com.spring.service.impl.Chinese">
        <!-- 将StoneAxe注入给axe属性 -->
        <property name="axe" ref="stoneAxe" />
        <property name="name" value="孙悟空"/>
    </bean>
    <!-- 配置stoneAxe实例 -->
    <bean id="stoneAxe" class="com.spring.service.impl.StoneAxe" />
</beans>

id:指定该Bean的唯一标识,程序会通过id属性值来访问该Bean实例。
class:指定该Bean的实现类,此处不可再用接口,必须是实现类,Spring容器会使用XML解析器读取该属性值,并利用反射来创建该实现类的实例。
从上面可以看出Bean于Bean之间的依赖关系放在配置文件里组织,而不是写在代码里。通过配置文件的指定,Spring能够精确地为每个Bean注入属性。因此,配置文件里的

构造注入


2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <!-- 配置Chinese实例 -->
    <bean id="chinese" class="com.spring.service.impl.Chinese">
        <!-- 使用构造注入,为Japanese实例注入SteelAxe实例-->
        <constructor-arg ref="stoneAxe"/>
    </bean>
    <!-- 配置stoneAxe实例 -->
    <bean id="stoneAxe" class="com.spring.service.impl.StoneAxe" />
</beans>

两种注入方式的对比

Spring支持两种依赖注入方式,这两种依赖注入方式并没有好坏之分,只是适合的场景有所不同。

设值注入有如下优点:

与传统的JavaBean的写法更相似,程序开发人员更加容易理解,接受。通过setter方法设定依赖关系显得更加直观、自然。
对于复杂的依赖关系,如果采用构造注入,会导致构造器过于臃肿,难以阅读。Spring在创建Bean实例时,需要同时实例化其依赖的全部实例,因此导致性能下降。而设值注入,则可以避免这些问题。
尤其是在某些属性可选的情况下,多参数的构造器更加笨重。
但是构造器也有如下优势:

构造注入可以再构造器中决定依赖关系的注入顺序,优先依赖的优先注入。

对于依赖关系无须变化的Bean,构造注入更有用处。

因为没有setter方法,所有的依赖关系全部在构造器中设定,因此,无须担心后续的代码对依赖关系产生破坏。
依赖关系只能在构造器中设定,则只有组件的创建者才能改变组件的依赖关系。对组件的调用者而言,组件内部的依赖关系完全透明,更加符合高内聚的原则。

Spring会自动接管每个

创建bean的集中方式

1.最简单的声明 Bean

简单的 Bean 是由 标签包裹,其中两个属性:
id 的作用是作为 Bean 的唯一标识,以后使用 Bean 的时候就使用 id 后面的名字即可;
class 的作用是作为制定该 Bean 的实现类,运行中 Spring 会 new 该实现类的对象,因此 class 必须指向实现类,而非其他接口等。

2.通过构造器声明

<bean id="HelloWorld" class="com.hundsun.spring.HelloWorld"> 
    <constructor-arg value="TOM"></constructor-arg> 
</bean> 

与简单声明 Bean 方法有所区别的是, 标签中增加了一个 标签,此标签中有 value 属性。多出的这个 constructor-arg 标签的作用就是为了填充目标实现类中含有参数的构造器中的参数。

3.通过工厂方法创建 Bean

工厂方法创建 Bean 的方法适用于单例类实例,即实例中只含有静态方法。
例如代码

<bean id="staticFunction" class="com.hundsun.spring.StaticHello" factory-bean="HelloWorld"></bean> 

相对简单方法,多出来一个 factory-bean 的属性,该属性指向的就是 StaticHello 实现类中 HelloWorld 静态方法。

4.使用 Set 方法注入 Bean 属性

要为创建 Bean 的实现类中的私有属性注入值,需要使用 Set 方法注入,简单安全。

要实现 set 方法注入 Bean 要做这样的步骤

1.在实现类中为目标私有属性生成 set 方法。
2.在构造 Bean 的 XML 文件中增加

例如代码

<bean id="demo" class="com.hundsun.spring.HelloWorld"> 
    <property name="message" value="你好"></property> 
</bean>

对应的 name 属性指的是 HelloWorld 实现类中 message 的私有属性,并且将 value 属性中的“你好”注入给 message。这个时候你若输出 message ,则会输出汉字“你好”。但是前提是你一定一定要在实现类中生成好 setMessage() 方法。

同样的,你可以给 Bean 属性赋值已有的其他 Bean,如代码所示。

<!-- 事先声明好的person的bean --> 
<bean id="Sam" class="com.hundsun.spring.entity.Person"></bean> 

<bean id="demo" class="com.hundsun.spring.HelloWorld"> 
    <property name="message" value="你好"></property> 
    <property name="person" ref="Sam"></property> 
</bean> 

一个 id 名为 Sam 的 Bean 被一个 id 为 demo 的 Bean 引用,关键属性为 ref ,ref 直接指向了已有的 Bean。

假设我只希望名为 Sam 的 Bean 被 demo 引用,我可以使用注入内部 Bean,只需将上述代码修改为这样:

<bean id="demo" class="com.hundsun.spring.HelloWorld"> 
    <property name="message" value="你好"></property> 
    <property name="person"> 
        <bean id="Sam" class="com.hundsun.spring.entity.Person"></bean> 
    </property> 
</bean> 

让Bean获取Spring容器

实现BeanFactoryAware接口的Bean,拥有访问的BeanFactory容器的能力,实现BeanFactoryAware接口的Bean实例将会拥有对容器的访问能力。BeanFactoryAware接口仅有如下一个方法:


2
3
4
5
6
7
8
9
10
11
12
13
14
public class Chinese implements ApplicationContextAware{
    //将BeanFactory容器以成员变量保存
    private ApplicationContext ctx;
    /** * 实现ApplicationContextAware接口实现的方法 */
    public void setApplicationContext(ApplicationContext cyx)  throws BeansException {
        this.ctx = ctx;
    }
    //获取ApplicationContext的测试方法
    public ApplicationContext getContext(){
        return ctx;
    }
}

2
3
4
5
6
7
8
9
10
11
12
13
14
public class Chinese implements ApplicationContextAware{
    //将BeanFactory容器以成员变量保存
    private ApplicationContext ctx;
    /** * 实现ApplicationContextAware接口实现的方法 */
    public void setApplicationContext(ApplicationContext cyx)  throws BeansException {
        this.ctx = ctx;
    }
    //获取ApplicationContext的测试方法
    public ApplicationContext getContext(){
        return ctx;
    }
}

Bean的基本定义

default-lazy-init :延迟初始化
default-merge:merge行为
default-autowire:自动装配行为
default-autowire-candidates:自动装配候选bean
default-init-method:初始化方法
default-destroy-method:回收方法

list、set、map、props

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- 定义一个普通的Axe Bean -->
<bean id="steelAxe" class="com.spring.service.impl.SteelAxe" />
<bean id="stoneAxe" class="com.spring.service.impl.StoneAxe" />

<!--定义Chinese Bean -->
<bean id="chinese" class="com.spring.service.impl.Chinese">
<property name="schools">
<list>
    <value>小学</value>
    <value>中学</value>
    <value>大学</value>
</list>
</property>

<property name="scores">
<map>
    <entry key="语文" value="88" />
    <entry key="数学" value="87" />
    <entry key="外语" value="88" />
</map>
</property>

<property name="phaseAxes">
<map>
    <entry key="原始社会" value-ref="stoneAxe" />
    <entry key="农业社会" value-ref="steelAxe" />
</map>
</property>

<property name="health">
<props>
    <prop key="血压">正常</prop>
    <prop key="身高">175</prop>
</props>
</property>

<property name="axe">
<set>
    <value>普通字符串</value>
    <bean class="com.spring.service.impl.SteelAxe"></bean>
    <ref local="stoneAxe"/>
</set>
</property>

<property name="books">
<list>
    <value>java 编程思想</value>
    <value>思考致富</value>
    <value>将才</value>
</list>
</property>
</bean>
</beans>

从上面的配置文件中可以看出,Spring对list属性和数组属性的处理是一样的。

当我们使用

所以这些元素又可以接受如下子元素:

value:指定集合元素是基本数据类型或者字符类型值。
ref:指定集合元素师容器中另一个Bean实例。
bean:指定集合元素是一个嵌套Bean。
list、set、map、props:指定集合元素值又是集合。

使用

Bean 的作用域

标签中的 scope 属性,该属性作用是控制 Bean 的作用域,默认情况下,Bean 是单例,即如果创建,如果被再次使用的话不会创建新的,而取之前创建过的 Bean 使用,如果想要每次都创建新的实例,则需要修改 scope 属性。

scope 属性值有:
singleton 一个 Bean 只有一个对象(默认)
prototype 每次都被重新创建一个实例
request 在一次 HTTP 请求中有效
session 在一次对话中有效
global-session 在整个 HTTP 请求中有效

初始化和销毁 Bean

两个属性:
init-method=””
在初始化 Bean 时执行实例中的某个方法。
destory-method=””
在 Bean 销毁时执行实例中的某个方法。
如果希望设置默认初始化和销毁方法的话,可以在文件头部标签中增加两个属性:
default-init-method=””
default-destory-method=”“

我的微信二维码如下,欢迎交流讨论

这里写图片描述

欢迎关注《IT面试题汇总》微信订阅号。每天推送经典面试题和面试心得技巧,都是干货!

微信订阅号二维码如下:

这里写图片描述

参考:
http://howiefh.github.io/2015/03/06/spring-note-1/
http://www.yelook.com/1637.html

© 著作权归作者所有

共有 人打赏支持
fengsehng
粉丝 4
博文 284
码字总数 214494
作品 0
朝阳
程序员
java,求大神解救一下,配置文件都是对的。

### Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot creat......

MrZZHHGG ⋅ 05/21 ⋅ 0

java问题,求大神解救一下小弟,谢谢好心人!非常感谢

### Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot creat......

MrZZHHGG ⋅ 05/21 ⋅ 0

SpringBoot bean注入失败

使用springboot+zookeeper+dubbo开发分布式应用 provider.xml

ysjO ⋅ 04/23 ⋅ 0

Spring系列之Spring常用注解总结

传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop、事物,这么做有两个缺点: 1、如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大;如果按需求分开.xml文件,那么...

HJCui ⋅ 05/29 ⋅ 0

深入理解Spring源码(一)-IOC容器的定位,载入,注册

前言:Spring源码继承,嵌套层次非常多,读起来非常容易晕,小伙伴们在看文章的时候一定要跟着文章的思路自己去源码里点一点,看一看,并且多看几次。就会越来越清晰。下面开始正题 1.Spring...

Meet相识_bfa5 ⋅ 05/01 ⋅ 0

spring4.0之二:@Configuration的使用

从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfi...

文文1 ⋅ 06/01 ⋅ 0

SSM整合,个人总结和step

我最近才整合完SSM。 前段时间,分开学习了这三个框架,都是看某黄埔军校的视频,整合的部分没看视频,想自己做。 但是有一些部分自己没有能完成,主要是如何从spring容器里取出Application...

wzlhlhhh ⋅ 05/11 ⋅ 0

初学spring-mvc

今天初步了解了一下springMVC,把自己对springmvc的一些理解总结了一下。 一、springmvc类似于Struts2的一种Web框架。 springmvc处理请求的流程: 1、用户发送请求,请求被Spring 前端控制S...

梁荣良 ⋅ 2016/05/12 ⋅ 0

Spring IOC知识点一网打尽!

前言 只有光头才能变强 回顾前面: 给女朋友讲解什么是代理模式 包装模式就是这么简单啦 单例模式你会几种写法? 工厂模式理解了没有? 在刷Spring书籍的时候花了点时间去学习了单例模式和工...

Java3y ⋅ 05/22 ⋅ 0

Spring中涉及的设计模式总结

Spring中涉及的设计模式总结 1.简单工厂(非23种设计模式中的一种) 实现方式:BeanFactory。 Spring中的BeanFactory就是简单工厂模式的体现,根据传入一个唯一的标识来获得Bean对象,但是否是...

caoxiaohong1005 ⋅ 04/22 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

mysql in action / alter table

change character set ALTER SCHEMA `employees` DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_general_ci ;ALTER TABLE `employees`.`t2` CHARACTER SET = utf8mb4 , COLLAT......

qwfys ⋅ 今天 ⋅ 0

Java 开发者不容错过的 12 种高效工具

Java 开发者常常都会想办法如何更快地编写 Java 代码,让编程变得更加轻松。目前,市面上涌现出越来越多的高效编程工具。所以,以下总结了一系列工具列表,其中包含了大多数开发人员已经使用...

jason_kiss ⋅ 昨天 ⋅ 0

Linux下php访问远程ms sqlserver

1、安装freetds(略,安装在/opt/local/freetds 下) 2、cd /path/to/php-5.6.36/ 进入PHP源码目录 3、cd ext/mssql进入MSSQL模块源码目录 4、/opt/php/bin/phpize生成编译配置文件 5、 . ./...

wangxuwei ⋅ 昨天 ⋅ 0

如何成为技术专家

文章来源于 -- 时间的朋友 拥有良好的心态。首先要有空杯心态,用欣赏的眼光发现并学习别人的长处,包括但不限于工具的使用,工作方法,解决问题以及规划未来的能力等。向别人学习的同时要注...

长安一梦 ⋅ 昨天 ⋅ 0

Linux vmstat命令实战详解

vmstat命令是最常见的Linux/Unix监控工具,可以展现给定时间间隔的服务器的状态值,包括服务器的CPU使用率,内存使用,虚拟内存交换情况,IO读写情况。这个命令是我查看Linux/Unix最喜爱的命令...

刘祖鹏 ⋅ 昨天 ⋅ 0

MySQL

查看表相关命令 - 查看表结构    desc 表名- 查看生成表的SQL    show create table 表名- 查看索引    show index from  表名 使用索引和不使用索引 由于索引是专门用于加...

stars永恒 ⋅ 昨天 ⋅ 0

easyui学习笔记

EasyUI常用控件禁用方法 combobox $("#id").combobox({ disabled: true }); ----- $("#id").combobox({ disabled: false}); validatebox $("#id").attr("readonly", true); ----- $("#id").r......

miaojiangmin ⋅ 昨天 ⋅ 0

金山WPS发布了Linux WPS Office

导读 近日,金山WPS发布了Linux WPS Office中文社区版新版本,支持大部分主流Linux系统,功能更加完善,兼容性、稳定性大幅度提升。本次更新WPS将首次在Linux提供专业办公文件云存储服务,实...

问题终结者 ⋅ 昨天 ⋅ 0

springboot2输出metrics到influxdb

序 本文主要研究一下如何将springboot2的metrics输出到influxdb maven <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-bo......

go4it ⋅ 昨天 ⋅ 0

微信小程序 - 选择图片显示操作菜单

之前我分享过选择图片这个文章,但是我在实际开发测试使用中发现一个问题在使用 wx.chooseImage 选择照片显示出第一格是拍照,后面是相册里的图片。这种实现之前说过了,效果如下。 但是你从...

hello_hp ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部