【Spring】Spring的bean装配
前言
bean
是Spring
最基础最核心的部分,Spring
简化代码主要是依赖于bean
,下面学习Spring
中如何装配bean
。
装配bean
Spring
在装配bean
时非常灵活,其提供了三种方式装配bean
。
- 在
XML
中进行显式配置。 - 在
Java
中进行显式配置。 - 隐式的
bean
发现机制和自动装配。
自动化装配bean
自动化装配技术最为便利,
Spring
从两个角度实现自动化装配。
- 组件扫描:
Spring
会自动发现应用上下文中所创建的bean
。 - 自动装配:
Spring
自动满足bean
之间的依赖。
自动装配示例
- pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.hust.grid.leesf.spring</groupId>
<artifactId>spring-learning</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>3.1.2.RELEASE</spring.version>
<cglib.version>3.1</cglib.version>
<junit.version>4.11</junit.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>${cglib.version}</version>
</dependency>
</dependencies>
</project>
- CompactDisc
package ch2;
interface CompactDisc {
void play();
}
其只定义了一个
play
接口,由子类实现。
- SgtPeppers
package ch2;
import org.springframework.stereotype.Component;
@Component
public class SgtPeppers implements CompactDisc {
private String title = "Sgt. Pepper's Lonely Hearts Club Band";
private String artist = "The Beatles";
public void play() {
System.out.println("Playing " + title + " by " + artist);
}
}
SgtPeppers
继承了CompactDisc
接口,使用Component
注释为一个Bean
。
- CDPlayerConfig
package ch2;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("ch2")
public class CDPlayerConfig {
}
配置类,
Spring
会自动加载上下文并扫描ch2
包下的所有bean
。
- CDPlayerTest
package ch2;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.junit.Assert.assertNotNull;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CDPlayerConfig.class)
public class CDPlayerTest {
@Autowired
private CompactDisc cd;
@Test
public void cdShouldNotNull() {
assertNotNull(cd);
}
}
该类用于测试是否成功装配
CompactDisc
的bean
,测试成功。
设置Bean名称
上述示例中
bean
的名称默认为sgtPeppers
,即将类名的首字母小写,当然可通过@Component("sp")
设置其名称为sp
;或者使用@Named("sp")
进行设置。
设置组建扫描基础包
上述示例中指定扫描
ch2
包,这是通过@ComponentScan("ch")
指定的,当然可以通过@ComponentScan(basePackages="ch2")
进行设置。若设置多个包,则可采用@ComponentScan(basePackages={"ch2","video"})
方式进行设置。除了使用字符串格式表明包名,也可使用类名格式,如@ComponentScan(basePackageClasses = SgtPeppers.class)
指定扫描类。
设置自动装配
示例中使用
@Autowired
实现自动装配,Spring
应用上下文中寻找某个匹配的bean
,由于示例中CompactDisc
只有一个声明为bean
的子类,若有多个声明为bean
的子类,则会报错,若没有子类,也会报错。@Autowired
注解不仅可以用在属性上,也可以用在构造函数上,还可以用在Setter方法上。若使用@Autowired(required=false)
时,那么没有符合的bean
时不会报错,而是处于未装配的状态,要防止空指针情况,其与@Inject
注解功能类似。
- 构造函数使用
@Autowired
注解
@Component
public class CDPlayer implements MediaPlayer {
private CompactDisc cd;
@Autowired
public CDPlayer(CompactDisc cd) {
this.cd = cd;
}
public void play() {
}
}
Setter
方法使用@Autowired
注解
@Autowired
public void setCompactDisc(CompactDisc cd) {
this.cd = cd;
}
在Java中显式配置
在配置类中显式配置
bean
,将CDPlayerConfig
中的@ComponentScan("ch2")
移除,此时运行测试用例会报错,下面通过显式配置方法来配置bean
。修改CDPlayerConfig
代码如下。
package ch2;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CDPlayerConfig {
@Bean
public CompactDisc sgtPeppers() {
return new SgtPeppers();
}
}
上述生成的
bean
名称与方法名相同,若想设置名称,可通过@Bean(name=sp)
进行设置。对于如下代码,调用sgtPeppers
会生成同一个sgtPeppers
的bean
,这是由于sgtPeppers
方法标记为Bean
,Spring
会拦截所有对该方法的调用,并且返回一个已经创建的bean
实例。默认情况下,Spring
中的bean
都是单例的。
@Bean
public CDPlayer cdPlayer() {
return new CDPlayer(sgtPeppers());
}
@Bean
public CDPlayer anotherCDPlayer() {
return new CDPlayer(sgtPeppers());
}
还可以使用如下方法来引用bean
@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc) {
return new CDPlayer(compactDisc);
}
这样会自动装配一个CompactDisc
到配置方法中,不用明确使用sgtPeppers
方法来构造CDPlayer
。
通过xml装配bean
除了使用
JavaConfig
来显式装配bean
外,还可以使用xml
文件来装配bean
。若想在xml
中声明一个bean
元素,则需要如下操作。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="sgtPeppers" class="ch2.SgtPeppers" />
</beans>
上述xml
文件中声明了一个名为sgtPeppers
的bean
,会调用SgtPeppers
的默认构造函数创建bean
。
使用构造器注入初始化bean
使用constructor-arg元素
<bean id="cdPlayer" class="ch2.CDPlayer">
<constructor-arg ref="compactDisc"/>
</bean>
上述代码表示将ID
为compactDisc
的bean
引用传递到CDPlayer
的构造器中。
使用c-命令空间
<bean id="cdPlayer" class="ch2.CDPlayer"
c:cd-ref="compactDisc"/>
</bean>
其中c:
表示命名空间前缀;cd
表示构造器参数名;-ref
表示注入的bean
的引用;compactDisc
表示要注入的bean
的ID
。
将字面量注入到构造器中
<bean id="compactDisc" class="ch2.BlankDisc">
<constructor-arg value="Sgt. Pepper's Lonely Hearts Club Band" />
<constructor-arg value="The Beatles" />
或者使用
<bean id="compactDisc" class="ch2.BlankDisc"
<c:_title="Sgt. Pepper's Lonely Hearts Club Band" />
<c:artist="The Beatles" />
装配集合到构造器中
装配字面量到List集合
<bean id="compactDisc" class="ch2.BlankDisc">
<constructor-arg value="Sgt. Pepper's Lonely Hearts Club Band" />
<constructor-arg value="The Beatles" />
<constructor-arg>
<list>
<value>Sgt.AA</value>
<value>Sgt.BB</value>
<value>Sgt.CC</value>
</list>
</constructor-arg>
</bean>
装配引用List集合
<bean id="compactDisc" class="ch2.BlankDisc">
<constructor-arg value="Sgt. Pepper's Lonely Hearts Club Band" />
<constructor-arg value="The Beatles" />
<constructor-arg>
<list>
<ref bean="sgtPeppers"/>
<ref bean="whiteAlbum"/>
<ref bean="revolver"/>
</list>
</constructor-arg>
</bean>
同理,对于Set
集合只需修改list
为set
即可。
设置属性
使用xml设置属性
<bean id="cdPlayer" class="ch2.CDPlayer">
<property name="compactDisc" ref="compactDisc">
</bean>
使用p-命令空间进行装配
<bean id="cdPlayer" class="ch2.CDPlayer"
p:compactDisc-ref="compactDisc">
</bean>
其组成与c-
类似。
将字面量装配到属性中
<bean id="compactDisc" class="ch2.BlankDisc">
<property name="title" value="Sgt. Pepper's Lonely Hearts Club Band" />
<property name="artist"value="The Beatles" />
<property name="tracks">
<list>
<value>Sgt.AA</value>
<value>Sgt.BB</value>
<value>Sgt.CC</value>
</list>
</property>
</bean>
使用p-装配属性
<bean id="compactDisc" class="ch2.BlankDisc">
<p:title="Sgt. Pepper's Lonely Hearts Club Band" />
<p:artist="value="The Beatles" />
<property name="tracks">
<list>
<value>Sgt.AA</value>
<value>Sgt.BB</value>
<value>Sgt.CC</value>
</list>
</property>
</bean>
使用util-命名空间装配集合
<util:list id="tractList">
<value>Sgt.AA</value>
<value>Sgt.BB</value>
<value>Sgt.CC</value>
</util:list>
此时对应修改如下
<bean id="compactDisc" class="ch2.BlankDisc">
<p:title="Sgt. Pepper's Lonely Hearts Club Band" />
<p:artist="value="The Beatles" />
<p:tracks-ref="trackList" />
</bean>
导入和混合配置
在JavaConfig中引用xml配置
将
BlankDisc
从CDPlayerConfig
中剥离出来,放置在自己的配置文件CDConfig
中。此时需要在CDPlayerConfig
中使用@Import(CDConfig.class)
将两者组合;或者使用更高级别的Config
中使用@Import({CDPlayerConfig.class,CDConfig.class})
组合两者。若将BlankDisc
配置在cd-config.xml
文件中,则可使用@ImportResource("classpath:cd-config.xml")
导入。
在xml配置中引用JavaConfig
可以使用
import
元素引用配置,如
<import resource="cd-config.xml" />
总结
Spring
有三种方式装配bean
,使用自动化装配技术使得代码更简洁;并且有多种方式注入属性。
【Spring】Spring的bean装配的更多相关文章
- 使用Spring IoC进行Bean装配
Spring概述 Spring的设计严格遵从的OCP(开闭原则),保证对修改的关闭,也就是外部无法改变spring内部的运行流程:提供灵活的扩展接口,也就是可以通过extends,implements ...
- Spring系列(二) Bean装配
创建应用对象之间协作关系的行为称为装配(wiring), 这也是DI的本质. Spring中装配Bean的方式 Spring提供了三种装配Bean的方式. 隐式的Bean发现机制和自动装配 Java ...
- Spring系列(三) Bean装配的高级技术
profile 不同于maven的profile, spring的profile不需要重新打包, 同一个版本的包文件可以部署在不同环境的服务器上, 只需要激活对应的profile就可以切换到对应的环境 ...
- Spring实战3:装配bean的进阶知识
主要内容: Environments and profiles Conditional bean declaration 处理自动装配的歧义 bean的作用域 The Spring Expressio ...
- Spring实战2:装配bean—依赖注入的本质
主要内容 Spring的配置方法概览 自动装配bean 基于Java配置文件装配bean 控制bean的创建和销毁 任何一个成功的应用都是由多个为了实现某个业务目标而相互协作的组件构成的,这些组件必须 ...
- Spring框架(3)---IOC装配Bean(注解方式)
IOC装配Bean(注解方式) 上面一遍文章讲了通过xml来装配Bean,那么这篇来讲注解方式来讲装配Bean对象 注解方式需要在原先的基础上重新配置环境: (1)Component标签举例 1:导入 ...
- Spring Bean装配方式
Spring装配机制 在xml中进行显示配置 在Java中进行显示配置 隐式bean发现机制和自动装配 自动化装配bean 组件扫描(component scanning),Spring会自动发现应用 ...
- Spring基础篇——bean的自动化装配
上篇博文讲Spring的IOC容器时说道,虽然容器功能强大,但容器本身只是个空壳,需要我们主动放入装配对象,并告诉它对象之间的协作关系,然后容器才能按照我们的指示发挥它的魔力,完成装配bean的使命. ...
- 使用spring框架,用xml方式进行bean装配出现“The fully qualified name of the bean's class, except if it serves...”
使用spring框架,用xml方式进行bean装配出现“The fully qualified name of the bean's class, except if it serves...”. 原 ...
随机推荐
- 【Eclipse】代码格式化 快捷键无效
原因:搜狗输入法 简繁切换与eclipse代码格式化冲突 解决:在搜狗输入法-->按键-->修改即可.
- 如何理解 Python 的赋值逻辑
摘要: 如果你学过 C 语言,那么当你初见 Python 时可能会觉得 Python 的赋值方式略有诡异:好像差不多,但又好像哪里有点不太对劲. 本文比较并解释了这种赋值逻辑上的差异.回答了为什么需要 ...
- jsp的C标签一般使用方法以及js接收servlet中的对象及对象数字
jsp的C标签一般使用方法以及js接收servlet中的对象及对象数组 由于现流行的javaWeb框架提倡前后端分离,比如在SpringMvc中已经很少写servlet的一些东西:目前 前端jsp中大 ...
- python基础学习(十三)
re模块包含对 正则表达式.本章会对re模块主要特征和正则表达式进行介绍. 什么是正则表达式 正则表达式是可以匹配文本片段的模式.最简单的正则表达式就是普通字符串,可以匹配其自身.换包话说,正则表达式 ...
- java 泛型简单使用
- Servlet之文件的上传与下载
文件上传和文件下载是我们学JAVA Web时必不可少的模块.今天我们探讨下这个问题 文件上传: request.setCharacterEncoding("utf-8");//设置 ...
- Android Studio发布项目到jcenter,一行代码引入Module
前面我们使用自己封装的okhttp项目时候,只需要app/build.gradle文件中加一行代码就能使用项目. compile 'com.ansen.http:okhttpencapsulation ...
- JavaScript中事件
JS中的事件 一.事件分类: 鼠标事件:鼠标单击.鼠标双击.鼠标指上等... HTML事件:文档加载.焦点.表单提交等... 键盘事件:键盘按下(keydown).键盘按下并松开瞬间(keypress ...
- 边看MHA源码边学Perl语言之一开篇
边看MHA源码边学Perl语言之一开篇 自我简介 先简单介绍一下自己,到目前为此我已经做了7年左右的JAVA和3年左右php开发与管理,做java时主要开发物流行业的相关软件,对台湾快递,国际快递,国 ...
- javascript中this的指向
作为一个前端小白在开发中对于this的指向问题有时候总是会模糊,于是花时间研究了一番. 首先this是JS的关键字,this是js函数在运行是生成的一个内部对象,生成的这个this只能在函数内部使用. ...