《Spring实战》系列之Bean的装配-Days01

1 自动化装配bean

Spring通过两个方面实现对bean的自动装配
1 )   组件扫描(component scaning):Spring会自动发现Spring上下文中的bean
2 )   自动装配(autowriting):Spring自动满足bean之间的依赖

1.1 创建可被发现的bean

  现在我们创建一个接口:
public interface CompactDisc {
    void play();
}

接着来一个实现类:

import org.springframework.stereotype.Component;

/**
* Created by cao zhiguo on 2017/9/1.
*/
@Component
public class SgtPeppers implements CompactDisc {
    private String title="享受孤独的音乐";
    private String article="奏出和谐的篇章";
    @Override
    public void play() {
        System.out.println(title+article);
    }

上述的@Component注解的含义是:声明该类是一个bean,此时Spring就有权利去管理这个对象,但是一般的情况下我们需要让Spring容器知道这个类是一个bean,光存在这个注解是不够的,因为Spring容器是发现不了这个注解的,此时可以开启注解的扫描模式,默认的情况下是关闭的。同样的有注解开启的方式和机遇XML的配置方式:比如我们正在CDPlayer这个类中开启这个自动注解的扫描;如下所示:因为我们要在这个类中使用SgtPeppers对象。

package cn.czg.springdemo02;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
* Created by cao zhiguo on 2017/9/1.
*/
@Configuration
@ComponentScan
public class CDPlayConfig {
}

上述中@Configuration的注解的作用是配置;@ComponentScan的作用是开启注解扫描,默认是该对象同包下的所有的类或者子包下的所有的类 
下面是基于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"
      xmlns:context="http://www.springframework.org/schema/context"
      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">
  <context:component-scan base-package="cn.czg.springdemo02"/>
</beans>

我们可以做相应的测试

package cn.czg.springdemo02;

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 junit.framework.TestCase.assertNotNull;

/**
* Created by cao zhiguo on 2017/9/1.
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CDPlayConfig.class)
public class CDPlayerTest {
    @Autowired
    private CompactDisc cd;

    @Test
    public void test(){
        assertNotNull(cd);
    }
}

上述中的测试: 
1) 使用的是SpringJunit4测试 
2) @ContextConfiguration(classes = CDPlayConfig.class)的作用是去类CDPlayerConfig中去加载配置,因为在CDPlayerConfig中包含了注解@ComponenScan注解。 
3) 因此我们最后使用的是断言测试,测试bean中包含CompactDisc这个对象吗。显然是测试通过的,是由Spring自行装配这个bean的。所有添加注解@Component都是bean,而使用ComponentScan注解就可以开启扫描。目前为止我们用到的一些注解及其作用做个总结: 
@Component org.springframework.stereotype.Component; 依赖Context包 
@Configuration org.springframework.context.annotation.Configuration; 依赖Context包 
@ComponentScan org.springframework.context.annotation.ComponentScan; 依赖Context包 
@RunWith(SpringJUnit4ClassRunner.class) org.junit.runner.RunWith; 依赖JUnit包以及Spring test包 
@ContextConfiguration(classes = CDPlayConfig.class) 
org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 依赖test包 
@Autowired org.springframework.beans.factory.annotation.Autowired; 依赖bean包 
@Test org.junit.Test; 依赖Junit测试

1.2 为组件扫描的bean命名

在使用XML配置bean的时候,我们一般用id来作为bean的唯一标识,但是使用注解也可以来实现:

package cn.czg.springdemo02;

import org.springframework.stereotype.Component;

/**
* Created by cao zhiguo on 2017/9/1.
*/
@Component("loneiest")
public class SgtPeppers implements CompactDisc {
    private String title="享受孤独的音乐";
    private String article="奏出和谐的篇章";
    @Override
    public void play() {
        System.out.println(title+article);
    }
}

在@Componenet(“xxx”)来为bean命名,作为唯一的标识,也可以使用Spring的依赖注入来完成.

package cn.czg.springdemo02;

import javax.inject.Named;

/**
* Created by cao zhiguo on 2017/9/1.
*/
/*@Component("loneiest")*/
@Named("loneiest")
public class SgtPeppers implements CompactDisc {
    private String title="享受孤独的音乐";
    private String article="奏出和谐的篇章";
    @Override
    public void play() {
        System.out.println(title+article);
    }
}

1.3 设置组件扫描的基础包

我们面临的问题是在上述的代码中,我们所有的类都在相同的包中进行的测试,因此@ComponentScan是没有任何属性的,但是如果我们要扫描不同的包该怎么实现呢?比如说我要装配的bean在不同的包中,此时我们就要为这个注解添加属性了。
基础包:就是以配置类所在的包为基础包,比如上述的代码我们要配置CDPlayerConfig类,因此他所在的包就是base-Package.但是如果我们的bean不在这个基础包中就尴尬了。我们的做法有下面的几种方式:
package cn.czg.springdemo02;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
* Created by cao zhiguo on 2017/9/1.
*/
@Configuration
@ComponentScan("cn.czg.springdemo02")
public class CDPlayConfig {
}

还有一种方式:设置基础包。两种方式都是一样的

package cn.czg.springdemo02;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
* Created by cao zhiguo on 2017/9/1.
*/
@Configuration
@ComponentScan(basePackages = "cn.czg.springdemo02")
public class CDPlayConfig {
}

大家可以看到,上述用到的是basePackages是复数的形式,因此可以以数组的形式扫描不同的包

package cn.czg.springdemo02;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
* Created by cao zhiguo on 2017/9/1.
*/
@Configuration
@ComponentScan(basePackages = {"cn.czg.springdemo02","cn.czg.gosaint"})
public class CDPlayConfig {
}

但是上述的做法还是不安全的,只能的IDE可能会提示你,但是不太智能的IDE应该不会提示你,因为你的基础包使用的是String类型的,因此什么类型都可以写,因此就有如下的做法,直接扫描具体的类。

package cn.czg.springdemo02;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
* Created by cao zhiguo on 2017/9/1.
*/
@Configuration
/*@ComponentScan(basePackages = {"cn.czg.springdemo02","cn.czg.gosaint"})*/
@ComponentScan(basePackageClasses ={ CompactDisc.class,SgtPeppers.class})
public class CDPlayConfig {
}

这样的做的更好的有点在于代码因重构,有可能包发生了变化,但是具体的类是没有改变的,我们的扫描依然是正确的。更加安全。

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

@Autowird的注解的使用

package cn.czg.springdemo02;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * Created by cao zhiguo on 2017/9/2.
 */
@Component
public class CDPlayer implements MediaPlayer {
    private CompactDisc sc;

    @Autowired
    public CDPlayer(CompactDisc sc) {
        this.sc = sc;
    }

    public void play(){
        sc.play();
    }
}

在这里CDPlay构造器在构建对象的过程中,同时把sc以参数传递进来,进行注入。这是通过该构造器进行实例化并且自动装配这个bean. 
@Autowired注解不仅可以用在构造器上,还可以用在setter方法或者任何方法之上。也是表明这种注入的关系。让我们下面看一看这两种的用法。

package cn.czg.springdemo02;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
* Created by cao zhiguo on 2017/9/2.
*/
@Component
public class CDPlayer implements MediaPlayer {
    private CompactDisc sc;

    @Autowired
    public CDPlayer(CompactDisc sc) {
        this.sc = sc;
    }

    /**
    * setter方法
    * @param sc
    */
    @Autowired
    public void setSc(CompactDisc sc) {
        this.sc = sc;
    }

    /**
    * 一般的额普通方法
    * @param sc
    */
    @Autowired
    private void insert(CompactDisc sc){
        this.sc=sc;
    }

    public void play(){
        sc.play();
    }
}

关于下一节我们就来验证自动装配是否成立。

 
 

原文地址:https://www.cnblogs.com/gosaint/p/8242118.html

时间: 2024-11-01 14:21:22

《Spring实战》系列之Bean的装配-Days01的相关文章

[Spring实战系列](9)装配集合

前两篇文章中,我们已经了解了如何使用Spring 配置简单属性值(使用value 属性)和引用其他Bean 的属性(使用ref 属性).但是value 和ref 仅在Bean 的属性值是单个值的情况下才有用.当Bean 的属性值是集合,Spring 该如何配置呢? 当配置集合类型的Bean属性时,Spring 提供了4 种类型的集合配置元素. 集合元素 用途 <list> 装配list类型的值,允许重复. <set> 装配set类型的值,不允许重复. <map> 装配m

Spring MVC系列-(2) Bean的装配

2. Bean的装配 Spring容器负责创建应用程序中的bean,并通过DI来协调对象之间的关系.Spring提供了三种主要的装配机制: XML显式配置: Java配置类进行显式配置: 隐式的bean发现机制和自动装配. 推荐使用Java配置类结合隐式的自动bean扫描机制. 2.1 通过XML装配Bean XML配置是Spring刚出现时的主要配置方式.这种方式需要手动编写XML,并在其中配置好Bean的定义. 创建XML并定义Bean 下面是Person类的定义, public class

Spring基础系列5 -- bean的基本用法

Spring基础系列5 -- bean的基本用法 转载:http://www.cnblogs.com/leiOOlei/p/3532604.html 本篇讲述了Bean的基本配置方法,以及Spring中怎样运用Bean. 主要内容如下: 一.      Spring中Bean的相互引用 二.      Spring中给Bean属性注入value 三.      Spring Inner Bean—内部嵌套的Bean 四.      Spring Bean Scopes—Bean的作用域 五.  

[Spring实战系列](11)SpEL使用表达式装配

到目前为止,我们为Bean 的属性和构造器参数装配的所有东西都是在Spring 的XML 配置文件中静态定义的. <bean id = "yoona" class = "com.sjf.bean.Student"> <property name="name" value = "yoona"/> <property name="hobby" value = "踢足球,打

[Spring实战系列](14)Bean的自动检测

即使<context:annotation-config>有助于完全消除Spring注解中的<property>和<constructor-arg>元素,但是还是不能完全消除,仍然需要使用<bean>元素显示定义Bean.因此<context:component-scan>元素出现了,它除了完成<context:annotation-config>一样的工作,还允许Spring自动检测Bean和定义Bean.这就意味着我们不使用<

[Spring实战系列](10)初探Bean生命周期

1. 生命周期流程图 Bean在Spring容器中从创建到销毁经历了若干个阶段,在每一个阶段都可以针对Spring如何管理Bean进行个性化定制. 正如你所见,在Bean 准备就绪之前,Bean 工厂执行了若干启动步骤. Spring 对Bean 进行实例化. Spring 将值和Bean 的引用注入进Bean 对应的属性中. 如果Bean 实现了BeanNameAware接口,Spring 将Bean的ID传递给setBeanName() 接口方法. 如果Bean 实现了BeanFactory

[Spring实战系列](6)配置Spring IOC容器的Bean

1. 简介 Spring提供了一个强大的IOC容器来管理组成应用的bean.为了利用容器服务,必须配置运行于Spring IOC容器中的Bean. 2. 解决方案 你可以通过XML文件,属性文件,注释甚至API来设置Spring IOC容器中的Bean. Spring允许你在一个或者多个bean配置文件中配置bean.对于简单的应用程序,可以在单个配置文件中集中配置bean.但是对于有许多bean的大型应用,你应该根据其功能将其分割到多个配置文件中. 3. 创建Spring配置 正如前面所讲的,

[Spring实战系列](8)Spring注入方式之setter注入

通常,JavaBean 的属性是私有的,同时拥有一组存取器方法,以setXXX() 和getXXX() 形式存在.Spring 可以借助属性的set方法来配置属性的值,以实现setter方式的注入. 1. 注入简单值 在Spring 中我们可以使用<property> 元素配置Bean 的属性.<property>在许多方面都与<constructor-arg> 类似,只不过一个是通过构造参数来注入值,另一个是通过调用属性的setter 方法来注入值. 举例说明,让我们

[Spring实战系列](15)使用Spring基于Java的配置

并不是所有的开发人员都喜欢使用XML,所以Spring3.0 为这些人准备了一些特别的东西.可以几乎不使用XML而使用纯粹的Java代码来配置Spring应用.并且基于Java的配置拥有一些XML配置所不具有的技巧. 1. 创建基于Java的配置 即使Spring的Java配置可以让我们不使用XML就可以编写大多数的Spring配置,但是我们仍然需要极少量的XML来启用Java配置. <?xml version="1.0" encoding="UTF-8"?&