一、Spring装配-自动化装配

@Component和@ComponentScan

通过spring注解(@Component)来表明该类会作为组件类,并告知Spring要为这类创建bean,不过组件扫描默认是不启动的,需要显式的配置Spring,从而命令Spring去寻找带有(@Component)注解的类,并为其创建bean。

1、定义接口

package com.seven.springTest.service;

public interface HelloWorldApi {
public void sayHello();
}

2、定义接口的实现类

package com.seven.springTest.service.impl;

import org.springframework.stereotype.Component;

import com.seven.springTest.service.HelloWorldApi;

@Component    //通过注解指定该类组件类,告知spring要为它创建Bean
public class PersonHelloWorld implements HelloWorldApi { @Override
public void sayHello() {
System.out.println("Hello World,This Is Person!");
}
}

3、前面说过了,spring并不能自动启用组件扫描,需要进行显式的配置,这里通过java类来进行显式的配置,定义java配置类HelloWorldConfig,在配置类中我们没有显式的声明任何bean,只不过是使用了@CompontentScan注解来启用组件扫描

package com.seven.springTest;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; @Configuration
@ComponentScan // 启用组件扫描
public class HelloWorldConfig { }

现在所有的工作已经完成,我们来测试下

package com.seven.springTest.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.seven.springTest.HelloWorldConfig;
import com.seven.springTest.service.HelloWorldApi; public class HelloWorldTest { public static void main(String[] args) {
//1. 声明Spring上下文,采用java配置类
ApplicationContext ac = new AnnotationConfigApplicationContext(HelloWorldConfig.class);
//2. 声明Spring应用上下文,采用xml配置
//ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
//通过Spring上下文获取Bean,在这里Spring通过自动扫描发现了PersonHelloWorld的实现,并自动创建bean。
HelloWorldApi hwapi = ac.getBean(HelloWorldApi.class);
//通过sayHello()的输入内容可以看到,hwapi为PersonHelloWorld的实例
hwapi.sayHello();
}
}

通过上的代码,在控制台会输出下面的内容 “Hello World,This Is Person!”

Spring容器通过组件扫描发现了PersonHelloWorld类,并为它创建了对应的bean。到此为止,我们通过简单的注解实现自动化装配,在上面的案例中,HelloWorldConfig配置类@ComponentSan如果没有其他配置,只会扫描HelloWorldConfig所在包或者它的子包,如果需要制定扫描的包,可以通过

@ComponentScan("com.seven.springTest")

或者

@ComponentScan(basePackages="com.seven.springTest")

basePackages允许设置多个包,,只需要把basePackages熟悉设置成一个数组即可

@ComponentScan(basePackages={"com.seven.springTest.service","com.seven.springTest.impl"})

除了通过java配置类来设置Spring启用组件扫描,还可能通过xml类显式配置,参考下面xml配置,并在获取Spring应用上下文时通过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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd"> <!-- 启用Spring组件扫描-->
<context:component-scan base-package="com.seven.springTest"></context:component-scan> </beans>

在上面的案例中,我们通过@Component和@ComponentScan来隐式的配置完成了Bean的装配工作接下来我们深入的探讨下@Component和@ComponentScan

Spring容器在管理Bean的时候,会给每一个Bean有一个ID标识,上面的例子,如果HelloWorldApi的实现类有多个,那么Spring容器该怎么分配Bean呢,如果我们在使用@Component的时候,没有明确的给PersonHelloWorld设置一个ID,Spring容器会默认给bean给定一个ID,一般为类名(第一个字母会变为小写,例如跑personHelloWorld),所以下面的代码也是成立的

//通过bean的ID来获取实例
HelloWorldApi hwapi = (HelloWorldApi) ac.getBean("personHelloWorld");
hwapi.sayHello();

同时我们也可以为bean设置ID,如下:

@Component("person")    //为bean设置ID为“person”
public class PersonHelloWorld implements HelloWorldApi { @Override
public void sayHello() {
// TODO Auto-generated method stub
System.out.println("Hello World,This Is Person!");
} }

这样我们在获取bean的时候就可通过ID来获取,如下:

// 根据设置的bean ID来获取bean
HelloWorldApi hwapi = (HelloWorldApi) ac.getBean("person");

在以上的案例中我们使用了@Component和@ComponentScan实现了组件扫描,目前为止我们都是对单一的对象进行操作,如果程序复杂点,对象之间存在依赖,该如何处理呢?下面我们就来研究下如何为bean添加注解实现自动装配

@AutoWired

在上面的案例中Person对整个世界说了一句Hello,可说话只有旁边的人知道,我们需要让更多的听到我们的“hello world”,我们就需要一些工具,我们使用电视来广播就能让更多的人听到了,首先我们定义一个传播工具接口

package com.seven.springTest.service;

public interface TransmittingTool {
void work(String message);
}

接下来我们来创建我们的TV

package com.seven.springTest.service.impl;
import org.springframework.stereotype.Component; import com.seven.springTest.service.TransmittingTool; @Component //设置为需要被扫描到的组件
public class TVTool implements TransmittingTool { @Override
public void work(String message) {
//传播工具工作,把我们的消息传播出去
System.out.println(message);
}
}

接下来我们需要对我们之前的PersonHelloWorld的sayHello()方法进行一些修改,让它可以通过传播工具来对全世界说Hello

package com.seven.springTest.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import com.seven.springTest.service.HelloWorldApi;
import com.seven.springTest.service.TransmittingTool; @Component
public class PersonHelloWorld implements HelloWorldApi {
//定义传播工具
@Autowired //1.直接变量添加注解
private TransmittingTool transmittingTool; // @Autowired //2. 通过构造函数注入依赖
// public PersonHelloWorld(TransmittingTool transmittingTool) {
// this.transmittingTool = transmittingTool;
// } // @Autowired //3. 通过属性的Setter方法注入依赖
// public void setTransmittingTool(TransmittingTool transmittingTool) {
// this.transmittingTool = transmittingTool;
// } // @Autowired //4. 通过其他函数注入依赖
// public void inserttool(TransmittingTool transmittingTool){
// this.transmittingTool=transmittingTool;
// } @Override
public void sayHello() { // 通过传播工具来sayHello
transmittingTool.work("Hello World,This Is Person!--form TV");
}
}

首先我们定义了一个传播工具,这个工具的具体实现我们不清楚,需要Spring容器去给我注入依赖。
@Autowired直接可以使用在类变量、构造函数、Setter和其他任何方法上,参考代码中1-4的实现

  1. 直接在变量上添加注解
  2. 在构造函数上添加注解,在spring容器通过构造器实例化bean的时候,会传入一个提供给transmittingTool的实例,注入依赖;
  3. 通过Setter方法或者其他函数,Spring在初始化bean以后,会尽量的去满足bean的所有依赖,如果使用第4个种注入,我们在HelloWorldTest中重来没有调用过inserttool()方法,可是sayHello()还是能正常执行,Spring会去根据@Autowired来尽量尝试去注入PersonHelloWorld的依赖

如果能够配置到1个满足要求的依赖,那么这个被依赖的bean就会被装配进来,如果没有匹配的依赖bean,那么应用上下文创建的时候,Spring会抛出一个异常,为了避免异常,我们可以把@Autowired的required设置为false

@Autowired(required=false)   //2. 通过构造函数注入依赖
public PersonHelloWorld(TransmittingTool transmittingTool) {
this.transmittingTool = transmittingTool;
}

@Autowired的required设置给false后,Spring为尝试给bean自动装配,注入依赖,如果没有匹配的bean的话,Spring将会让这个bean处于未装配的状态,当时把required设置为false的时需要注意,因为这个依赖bean处于未装配状态,在调用依赖的时候,如果你的代码做null的检查,这个处于未装配状态的属性有可能会发生异常。

如果有多个bean能满足依赖关系的话,Spring也会抛出异常,表明没有明确指出选择哪个bean进行自动装配。这个在后面我会单独开一篇讲解Spring的高级装配,到时候在详细说明,大家可以关注后续的文章。

自动化装配Bean的更多相关文章

  1. 第2章—装配Bean—自动化装配Bean

    自动化装配Bean 2.1.Spring配置可选方案 ​ 装配是依赖注入DI的本质,Spring提供了以下三种注入的装配机制: 在XMl中进行显式配置 在java中进行显式配置 隐式的Bean发现机制 ...

  2. Spring 之自动化装配 bean 尝试

    [Spring之自动化装配bean尝试] 1.添加dependencies如下所示(不是每一个都用得到 <dependencies> <dependency> <grou ...

  3. Spring学习系列(二) 自动化装配Bean

    一.Spring装配-自动化装配 @Component和@ComponentScan 通过spring注解(@Component)来表明该类会作为组件类,并告知Spring要为这类创建bean,不过组 ...

  4. Spring入门(二):自动化装配bean

    Spring从两个角度来实现自动化装配: 组件扫描(component scanning):Spring会自动发现应用上下文中需要创建的bean. 自动装配(autowiring):Spring会自动 ...

  5. Spring自动化装配bean

    1. 场景 用CD(Compact disc)和CD播放器(CDPlayer)阐述DI(依赖注入). 如果不将CD插入(注入)到CDPlayer中,那么CDPlayer其实没有太大的用处,所以,可以这 ...

  6. Spring in action读书笔记(一) 自动化装配bean

    需要引入的ja包 <dependency> <groupId>org.springframework</groupId> <artifactId>spr ...

  7. SpringInAction读书笔记--第2章装配Bean

    实现一个业务需要多个组件相互协作,创建组件之间关联关系的传统方法通常会导致结构复杂的代码,这些代码很难被复用和单元测试.在Spring中,对象不需要自己寻找或创建与其所关联的其它对象,Spring容器 ...

  8. Spring学习笔记(二)之装配Bean

    一,介绍Bean的装配机制 在Spring中,容器负责对象的创建并通过DI来协调对象之间的关系.但是我们要告诉Spring创建哪些Bean并且如何将其装配在一起.,装配wiring就是DI依赖注入的本 ...

  9. 笔记3 装配Bean总结

    一.自动化装配bean 1.组件扫描 2.自动装配 CompactDisc.java package Autowiring; public interface CompactDisc { void p ...

随机推荐

  1. Python环境准备(安装python解释器)

    上篇文章介绍了Python的相关知识,本章就开始着手操作,创建第一个Python程序,在这之前,首先需要配置Python的运行环境,也就是安装python解释器 ------------- 完美的分割 ...

  2. vue实现简单评分效果

  3. iOS内存管理(objective-c)

    移动app开发中,由于移动设备内存的限制,内存管理是一个非常重要的话题.objective-c的内存管理,不仅是面试当中老生常谈的一个必问话题,也是日常项目开发中,特别需要重视的环节.对于笔者这种以j ...

  4. Luogu 1452 Beauty Contest

    Luogu 1452 Beauty Contest 求平面最远点对,先求出凸包,再找凸包的直径. 使用旋转卡壳,直径一定出现在对踵点对间.比较不同点到同一直线距离可以用叉积算三角形面积来比较. 实现时 ...

  5. POJ2185 Milking Grid 【lcm】【KMP】

    Description Every morning when they are milked, the Farmer John's cows form a rectangular grid that ...

  6. BZOJ4557 JLoi2016 侦察守卫 【树形DP】*

    BZOJ4557 JLoi2016 侦察守卫 Description 小R和B神正在玩一款游戏.这款游戏的地图由N个点和N-1条无向边组成,每条无向边连接两个点,且地图是连通的.换句话说,游戏的地图是 ...

  7. 《DSP using MATLAB》示例Example 6.28

    代码: % The following 3 lines produce filter coefficients shown in Table 6.1 wp = [0.35, 0.65]; ws = [ ...

  8. filter添加水印

    1filter写法 先定义自己的responseWrapper chain.doFilter(request,responseWrapper); responseWrapper来输出 package ...

  9. C# Socket Post File

    ///<summary> ///向服务器发送混合型的请求,1:成功发送,0:发送失败 ///</summary> ///<param name="paranam ...

  10. redis+php实现微博功能(三)

    个人主页显示微博列表(自己及关注人的微博列表) /*获取最新的50微博信息列表,列出自己发布的微博及我关注用户的微博 *1.根据推送的信息获取postid *2.根据postid获取发送的信息 */ ...