什么是Bean?

Spring Bean是被实例的,组装的及被Spring 容器管理的Java对象。

Spring 容器会自动完成@bean对象的实例化。

创建应用对象之间的协作关系的行为称为:装配(wiring),这就是依赖注入的本质。

Spring 三种配置方案

1.在XML中进行显示配置

2.使用Java代码进行显示配置

3.隐式的bean发现机制和自动装配

推荐方式: 3>2>1

一、自动化装配bean

1.组件扫描(component scanning):Spring 会自动发现应用上下文中所创建的bean。

2.自动装配(autowiring):Spring自动满足bean之间的依赖。

package com.stalkers;

/**
* CD唱片接口
* Created by stalkers on 2016/11/17.
*/
public interface ICompactDisc {
void play();
}
package com.stalkers.impl;

import com.stalkers.ICompactDisc;
import org.springframework.stereotype.Component; /**
* Jay同名专辑
* Created by stalkers on 2016/11/17.
*/
@Component
public class JayDisc implements ICompactDisc { private String title = "星晴"; public void play() {
System.out.println(title + ":一步两步三步四步,望着天上星星...");
}
}

Component注解作用:

表明该类会作为组件类。

不过,组件扫描默认是不开启用的,我们还需要显示配置下Spring,从而命令它去寻找带有@Component注解的类,并为其创建bean。

1.java code开启组件扫描:

其中,如果CompoentScan后面没有参数的话,默认会扫描与配置类相同的包

@Configuration
@ComponentScan
public class CDPlayerConfig {
@Bean
public ICompactDisc disc() {
return new JayDisc();
}
}

2.xml启动组件扫描

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.stalkers.impl"/>
</beans>

测试代码

package com.stalkers;

import com.stalkers.config.CDPlayerConfig;
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; /**
* Created by stalkers on 2016/11/18.
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CDPlayerConfig.class)
public class TestPlay {
@Autowired
private ICompactDisc jayDisc; @Test
public void play() {
jayDisc.play();
}
}

在ComponentScan扫描的包中,所有带有@Component注解的类都会创建为bean

为组件扫描的bean命名

Spring应用上下文种所有的bean都会给定一个ID。在前面的例子中,尽管我们没有明确地为JayDisc bean设置ID,但是Spring会默认为JayDisc设置ID为jayDisc,也就是将类名的第一个字母变成小写

如果想为这个bean设置不同的ID,那就将期望的值传递给@Component注解

@Component("zhoujielun")
public class JayDisc implements ICompactDisc {
...
}

如果不使用@Component注解的话,则使用Java依赖注入规范(Java Dependency Injection)中所提供的@Named注解bean的ID。

需要引入:

   <dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
@Named("zhoujielun")
public class JayDisc implements ICompactDisc {
....
}

设置组件扫描的基础包

前面再给CDPlayerConfig类设置@ComponentScan,我们并没有设置任何属性,这个时候默认扫描默认包是:CDPlayerConfig类所在包及其包的子包。

如果是下图这种情况,DisConfig与其这时候就需要设置@ComponentScan的扫描的包。

@Configuration
@ComponentScan(basePackages = {"com.stalkers.soundsystem"})
public class DiscConfig {
}

basePackages使用的是复数,则意味着可以设置多个基础包。

但是basePackages后面跟的是String类型,这种类型并不安全。可以使用basePackageClasses有下面这种写法:

@Configuration
@ComponentScan(basePackageClasses = {com.stalkers.soundsystem.JayCompactDisc.class})
public class DiscConfig {
}

通过为bean添加注解实现自动装配

如果所有的对象都是独立的,彼此之间没有任何依赖,那么使用组件扫描就能自动化装配bean。

但是实际工作中,很多对象会依赖其他对象完成任务。这时候就需要能够将组件扫描得到的bean和他们依赖装配在一起。这就是自动装配(autowiring)

使用Spring的Autowired

public interface IMediaPlayer {
void play();
}
@Component
public class CDPlayer implements IMediaPlayer { private ICompactDisc cd; @Autowired
public CDPlayer(ICompactDisc cd) {
this.cd = cd;
} public void play() {
System.out.println("cd Play:");
cd.play();
}
}

CDPlayer类的构造器上添加了@Autowired注解,表明当Spring创建CDPlayerbean的时候,会通过这个构造器来进行实例化

Autowired的多种方式

1.构造器注解(constructor)

2.属性setter注解

3.field注解

不管使用上面3中的哪个方法,Spring都会满足声明的依赖。假如有且只有一个bean匹配依赖的话,那么这个bean将会被装配进来。

如果使用2,3方式注解,有多个bean的话,则用Qualifier指定。

如果没有匹配的bean,那么在应用上下文创建的时候,Spring会抛出一个异常。为了避免异常的出现,可以使用

@Autowired(required = false)
private IMediaPlayer CDPlayer;

required=false表示如果没有匹配的话,Spring会让bean处于未装配的样子。使用未装配的属性,会出现NullPointerException

总结:

所以在使用开发的时候一般建议使用Resource(package javax.annotation)进行注解。但是Resource不支持构造器注解

二、通过Java代码装配Bean

尽管在很多场景下通过组件扫描和自动装配实现Spring的自动化更为推荐,但是有时候行不通。比如引用第三方组件,没办法在它的类上添加@Component及@Autowired。所以就需要JavaConfig或者XML配置

在进行显示配置的时候,JavaConfig是更好的解决方案。

JavaConfig与其他的Java代码又有所区别,在概念上它与应用程序中的业务逻辑和领域代码又有所不同。JavaConfig是配置相关代码,不含任何逻辑代码。通常会将JavaConfig放到单独的包中。

创建JavaConfig类

@Configuration
public class CDPlayerConfig {
}

使用@Configuration表明CDPlayerConfig是一个配置类

声明简单的bean

@Bean
public IMediaPlayer cdplayer() {
return new VCDPlayer(new JayCompactDisc());
}

@Bean注解会告诉Spring将返回一个对象。

默认情况下,@Bean的Id与带有@Bean的方法名一样。当然也可以通过@Bean的name属性指定额外的方法名。

借助JavaConfig注入

在上面的例子中,初始化个VCDPlayer都需要new一个JayCompactDisc对象。如果其他的对象的也需要JayCompactDisc,所以优化如下:

@Bean
public IMediaPlayer cdplayer() {
return new VCDPlayer(disc());
} @Bean
public ICompactDisc disc() {
return new JayCompactDisc();
}

单独抽出disc()方法,在其方法上加上Bean注解,Spring上加@Bean注解的都是默认单例模式,不管disc()被多个方法调用,其disc()都是同一个实例。

当然上面的初始化可以优化如下:

@Bean
public IMediaPlayer cdplayer(ICompactDisc disc) {
return new VCDPlayer(disc);
}

三、通过XML装配Bean

在xml配置中,创建一个xml文件,并且要以元素为根。

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"> </beans>

在使用xml的时候,需要在配置文件顶部声明多个xml模式(XML Schema Definition xsd)文件

对于我们需要配置bean的则在spring-beans模式中。

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="jayCompactDisc" class="com.stalkers.soundsystem.JayCompactDisc"></bean>
</beans>

1.借助构造器注入初始化bean

构造器注入的方案:

1.元素

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="jayCompactDisc" class="com.stalkers.soundsystem.JayCompactDisc"></bean>
<bean id="cdPlayer" class="com.stalkers.soundsystem.VCDPlayer">
<constructor-arg ref="jayCompactDisc"/>
</bean>
</beans>

2.使用Spring3.0所引入的c-命名空间

使用c-命名空间,需要引入:

xmlns:c="http://www.springframework.org/schema/c"
<?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:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="jayCompactDisc" class="com.stalkers.soundsystem.JayCompactDisc"></bean>
<bean id="cdPlayer" class="com.stalkers.soundsystem.VCDPlayer" c:cd-ref="jayCompactDisc">
</bean>
</beans>

解析:c-命名空间的语法:

c:cd-ref="jayCompactDisc"

1.c 代表命名空间前缀

2.cd 代表VCDPlayer类的构造器参数名。当然我们也可以使用参数在整个参数列表的位置 c:_0-ref

 <bean id="cdPlayer" class="com.stalkers.soundsystem.VCDPlayer" c:_0-ref="jayCompactDisc">

使用下划线因为参数不能以数字开头,所以加下划线。

3.-ref 代表注入bean引用

4.jayCompactDisc 要注入的bean的id

注意:

c-命名需要写在标签内,与constructor-arg写法差别很大

将字面量注入到构造器中

上面我们所做的DI通常指的是类型的装配,也就是将对象的引用装配到依赖他们的其他对象中,但是有时候我们传的只是一个字面量值

public class VaeCompactDisc implements ICompactDisc {
private String title; public VaeCompactDisc(String title) {
this.title = title;
} public void play() {
System.out.println("大家好,我是Vae,下面这首:" + title + "献给大家的");
}
}
<bean id="cdPlayer" class="com.stalkers.soundsystem.VCDPlayer" c:_0-ref="vaeCompactDisc">
</bean>
<bean id="vaeCompactDisc" class="com.stalkers.soundsystem.VaeCompactDisc">
<constructor-arg value="浅唱"></constructor-arg>
</bean>

c-命名空间的写法

<bean id="cdPlayer" class="com.stalkers.soundsystem.VCDPlayer" c:_0-ref="vaeCompactDisc">
</bean>
<bean id="vaeCompactDisc" class="com.stalkers.soundsystem.VaeCompactDisc" c:title="城府">
<!--<constructor-arg value="浅唱"></constructor-arg>-->
</bean>

装配集合

public class VaeCompactDisc implements ICompactDisc {
private String title; private List<String> tracks; public VaeCompactDisc(String title, List<String> tracks) {
this.title = title;
this.tracks = tracks;
} public void play() {
System.out.println("大家好,我是Vae,下面这专辑:" + title + "献给大家的");
for (String s : tracks) {
System.out.println(s);
}
}
}

Spring配置使用constructor-arg。而c-命名的是无法使用装配集合的功能

<bean id="cdPlayer" class="com.stalkers.soundsystem.VCDPlayer" c:_0-ref="vaeCompactDisc">
</bean>
<bean id="vaeCompactDisc" class="com.stalkers.soundsystem.VaeCompactDisc">
<constructor-arg name="title" value="自定义"></constructor-arg>
<constructor-arg name="tracks">
<list>
<value>有何不可</value>
<value>多余的解释</value>
</list>
</constructor-arg>
</bean>

2.使用属性Setter方法注入

public class CDPlayer implements IMediaPlayer {

    private ICompactDisc cd;

    @Autowired
public void setCd(ICompactDisc cd) {
this.cd = cd;
} public CDPlayer(ICompactDisc cd) {
this.cd = cd;
} public void play() {
System.out.println("cd Play:");
cd.play();
}
}

Spring.xml配置里面

<bean id="cdPlayer" class="com.stalkers.soundsystem.VCDPlayer">
<property name="cd" ref="jayCompactDisc"></property>
</bean>

元素为属性的Setter方法所提供的功能与元素为构造器所提供的功能是一样的。

与c-命名空间的类似的作为property的替代方案:p-命名空间。使用p-命名空间需要引入:

xmlns:p="http://www.springframework.org/schema/p"

Spring.xml配置如下

<bean id="cdPlayer" class="com.stalkers.soundsystem.VCDPlayer" p:cd-ref="vaeCompactDisc">

语法解析:

p:cd-ref="vaeCompactDisc"

1.p-:命名空间的前缀

2.cd:属性名称

3.-ref:注入bean引用

4.vaeCompactDisc:所注入的bean的id

将字面量注入到属性中

字面量注入到属性与上面将字面量注入到构造方法中方式一样。只不过标签名改成了property。

装配list也是与上面的构造器的装配list一样。

虽然我们无法使用c-及p-命名空间装配list,但是我们可以使用util:list

<bean id="vaeCompactDisc" class="com.stalkers.soundsystem.VaeCompactDisc" c:title="自定义" c:tracks-ref="songs">
</bean>
<util:list id="songs">
<value>有何不可</value>
<value>多余的解释</value>
</util:list>

Spring util命名空间的中的元素:

元素 描述
util:constant 引用某个类型的public static 域
util:list 创建一个java.util.List类型的bean,其中包含值或引用
util:map 创建一个java.util.Map类型的bean,其中包含值或引用
util:properties 创建一个java.util.Properties类型的bean
util:property-path 引用一个bean的属性
util: set 创建一个java.util.Set类型的bean

四、导入和混合配置

在Spring应用中,我们可以同时使用自动化和显示配置。

如果一个JavaConfig配置太臃肿,我们可以把其进行拆分,然后使用@Import将拆分的类进行组合。

如果希望在JavaConfig里引用xml配置。则可以使用@ImportResource

Spring Bean详细讲解的更多相关文章

  1. Spring MVC详细讲解

    一:三层架构和MVC 1:三层架构 我们的开发架构一般都是基于两种形式:一种是 C/S 架构,也就是客户端/服务器,另一种是 B/S 架构,也就是浏览器服务器.在 JavaEE 开发中,几乎全都是基于 ...

  2. Spring+EhCache缓存实例(详细讲解+源码下载)(转)

    一.ehcahe的介绍 EhCache 是一个纯Java的进程内缓存框架,具有快速.精干等特点,是Hibernate中默认的CacheProvider.Ehcache是一种广泛使用的开源Java分布式 ...

  3. Spring+EhCache缓存实例(详细讲解+源码下载)

    一.ehcahe的介绍 EhCache 是一个纯Java的进程内缓存框架,具有快速.精干等特点,是Hibernate中默认的CacheProvider.Ehcache是一种广泛使用的开源Java分布式 ...

  4. Spring Bean的生命周期(非常详细)

    Spring作为当前Java最流行.最强大的轻量级框架,受到了程序员的热烈欢迎.准确的了解Spring Bean的生命周期是非常必要的.我们通常使用ApplicationContext作为Spring ...

  5. 学妹问的Spring Bean常用配置,我用最通俗易懂的讲解让她学会了

    你好呀,我是沉默王二,一枚有趣的程序员,写的文章一直充满灵气,力求清新脱俗.昨天跑去王府井的小米店订购了一台小米 10,说是一周之内能到货,但我还是忍不住今天就想见到她.见我茶不思饭不想的,老婆就劝我 ...

  6. 2015年11月30日 spring初级知识讲解(一)装配Bean

    序,Spring的依赖注入是学习spring的基础.IOC为控制反转,意思是需要的时候就由spring生成一个,而不是先生成再使用. 写在前面 Spring提供面向接口编程,面向接口编程与依赖注入协作 ...

  7. Spring Bean的生命周期 ---附详细流程图及测试代码

    一.生命周期流程图: Spring Bean的完整生命周期从创建Spring容器开始,直到最终Spring容器销毁Bean,这其中包含了一系列关键点 假设一个Bean实现了所有的接口,大的概况一下Be ...

  8. Android webservice的用法详细讲解

    Android webservice的用法详细讲解 看到有很多朋友对WebService还不是很了解,在此就详细的讲讲WebService,争取说得明白吧.此文章采用的项目是我毕业设计的webserv ...

  9. spring入门详细教程(五)

    前言 本篇紧接着spring入门详细教程(三),建议阅读本篇前,先阅读第一篇,第二篇以及第三篇.链接如下: Spring入门详细教程(一) https://www.cnblogs.com/jichi/ ...

随机推荐

  1. 使用CSS3实现一个3D相册

    CSS3系列我已经写过两篇文章,感兴趣的同学可以先看一下CSS3初体验之奇技淫巧,CSS3 3D立方体效果-transform也不过如此 第一篇主要列出了一些常用或经典的CSS3技巧和方法:第二篇是一 ...

  2. 使用python抓取婚恋网用户数据并用决策树生成自己择偶观

    最近在看<机器学习实战>的时候萌生了一个想法,自己去网上爬一些数据按照书上的方法处理一下,不仅可以加深自己对书本的理解,顺便还可以在github拉拉人气.刚好在看决策树这一章,书里面的理论 ...

  3. 46张PPT讲述JVM体系结构、GC算法和调优

    本PPT从JVM体系结构概述.GC算法.Hotspot内存管理.Hotspot垃圾回收器.调优和监控工具六大方面进行讲述.(内嵌iframe,建议使用电脑浏览) 好东西当然要分享,PPT已上传可供下载 ...

  4. redis成长之路——(一)

    为什么使用redis Redis适合所有数据in-momory的场景,虽然Redis也提供持久化功能,但实际更多的是一个disk-backed的功能,跟传统意义上的持久化有比较大的差别,那么可能大家就 ...

  5. CSS三个定位——常规、浮动、绝对定位

    .dage { width: 868px; background: #5B8C75; border: 10px solid #A08C5A; margin-top: -125px; margin-le ...

  6. H3 BPM:为石化企业提供一个不一样的全停大修平台

    H3 BPM大型炼化企业装置全停检修管理平台(简称"全停大修")结合国际化的流程管理理念.成熟的系统技术架构.优秀的行业解决方案,为石油化工行业全停大修提供了卓越的信息化管理方案, ...

  7. RMS Server打开或关闭日志记录

    原文: https://technet.microsoft.com/zh-cn/library/cc732758 在 Active Directory Rights Management Servic ...

  8. Ubuntu下配置apache开启https

    一.HTTPS简述随着网络的日常,信息安全越来越重要,传统的网站都是http协议明文传输,而HTTPS协议是由SSL+HTTP协议构建的可进行加密传输.身份认证的网络协议,比http协议安全. 那ht ...

  9. Firebug中调试中的js脚本中中文内容显示为乱码

    Firebug中调试中的js脚本中中文内容显示为乱码 设置 页面 UFT-8 编码没用, 解决方法:点击 "Firebug"工具栏 中的"选项"---" ...

  10. NYOJ 975

    这道题一开始本着很朴素的想法就是先输入两头的数据,然后对每组的数据范围下测试中间的数据即可,但是是超时的.原因也很明显,比如计算1~1000的数据之后,假如下一组数据是1~1001,本来只需要多测试下 ...