Spring对bean的装配机制(一)——隐式自动装配

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gwd1154978352/article/details/76400877

Spring容器负责创建应用程序中的bean并通过DI来协调这些对象之间的关系,那Spring装配bean时是如何装配的呢?

Spring非常灵活,它提供了三种主要的装配机制:

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

2.在xml中进行显式装配。

3.在Java中进行显式装配。


本文对第一种机制进行详细说明:

一.自动装配bean

   spring从两个角度来实现自动化装配:

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

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

 说明:自动装配bean有两种方式,一种是java代码直接注解的形式,一种是xml配置的形式。xml配置的形式是目前国内大部分公司在用的,java代码直接注解的用的不多,不过个人觉得比xml的形式方便很多。


     (一)java形式的自动装配

                1.创建一个CompactDisc接口

package soundsystem;
/**
 *@作者:JackHisen(gwd)
 *@email:1154978352@qq.com
 *@时间:2017年7月29日 下午7:20:50
 *@version 1.0  
*/
public interface CompactDisc {
	void play();
}

                 2.创建CompactDisc接口的实现类

/**
 *@作者:JackHisen(gwd)
 *@email:1154978352@qq.com
 *@时间:2017年7月29日 下午7:21:38
 *@version 1.0  
*/
@Component//@Component("sgtPeppers")可以通过这样的方式来给bean设置id
public class SgtPeppers implements CompactDisc {
	private String title="Sgt.Pepper's Lonely Hearts Club Band";
	private String artist="The Beatles";
	
	public void play() {
		// TODO Auto-generated method stub
		System.out.println("Playing"+title+"by"+artist);
	}
}

SgtPeppers的具体内容并不重要,你需要注意的是SgtPeppers类上的@Component注解。这个简单的注解表名该类会作为组件类,并告知Spring要为这个类创建bean。没有必要显式配置SgtPeppers bean,因为这个类使用了@Component注解,所以Spring会为你把事情处理妥当。

不过,组件扫描默认是不启用的,所以我们还需要显式配置一下Spring,从而命令它去寻找带有@Component注解的类,并为其创建bean。CDPlayerConfig类展示了完成这项任务最简洁的配置。

注:还有另外一种bean命名的方式,这种方式不使用@Component注解,而是使用Java依赖注入规范中所提供的@Named注解来为bean设置ID。Spring支持将@Named作为@Component注解的替代方案。两者之间有些细微的差异,但是在大多数场景中,他们它们是可以相互替换的。


             3.开启组件扫描

package soundsystem;

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

/**
 *@作者:JackHisen(gwd)
 *@email:1154978352@qq.com
 *@时间:2017年7月29日 下午7:24:49
 *@version 1.0  
*/
@Configuration
@ComponentScan
public class CDPlayerConfig {
	
}

类CDPlayerConfig通过java代码定义了Spring的装配规则,它并没有显式地声明任何bean,不过使用了@ComponentScan注解,这个注解能够在Spring中启用组件扫描。

如果没有配置的话,@ComponentScan默认会扫描与配置类相同的包。因为CDPlayerConfig类位于soundsystem包中,因此Spring将会默认扫描这个包以及这个包下的所有子包,查找带有@Component注解的类。这样的话就能发现CompactDisc,并且会在Spring中自动为其创建一个bean。

@Configuration表名这个类是一个配置类,该类应该包含在Spring应用上下文中如何创建bean的细节。


注:@ComponentScan注解如果想要扫描其他包可以添加value值,如果想扫描多个基础包可以用用basePackages属性进行配置

@Configuration
@ComponentScan(value="soundsystem")
public class CDPlayerConfig {
	
}


@Configuration
@ComponentScan(basePackages={"soundsystem","otherpackage"})
public class CDPlayerConfig {
	
}

上面这个例子中,所设置的基础包是以 String类型表示的,这是可以的,但是这种方法是类型不安全的。如果你重构代码的话,那么所指定的基础包就可能会出错。

除了将包设置成String类型之外,@ComponentScan还提供了另外一种方法,那就是将其指定为包中所含的类或接口:

@Configuration
@ComponentScan(basePackageClasses={CompactDisc.class,otherExist.class})
public class CDPlayerConfig {
}


                   4.编写测试类

package soundsystem;

import static org.junit.Assert.*;
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;

/**
 *@作者:JackHisen(gwd)
 *@email:1154978352@qq.com
 *@时间:2017年7月29日 下午7:33:48
 *@version 1.0  
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=CDPlayerConfig.class)
public class CDPlayerTest {
	@Autowired
	private CompactDisc compactDisc;
	@Test
	public void cdShoudNotBeNull(){
		assertNotNull(compactDisc);
	}
}
CDPlayerTest使用了Spring的SpringJunit4ClassRunner,以便在测试开始的时候自动创建Spring的应用上下文。注解@ContextConfiguration会告诉它需要在CDPlayerConfig中加载配置。因为CDPlayerConfig类包含了@ComponentScan,因此最终的应用上下文应该包含CompactDisc bean。


扩展:

在上面的应用程序中,所有的对象都是独立的,彼此之间没有任何依赖,就行SgtPeppers bean这样,那么那你所需要的可能就是组件扫描而已。但是,很多对象会依赖其他的对象才能完成任务。这样的话,我们就需要一种方法能够将组件扫描得到的bean和它们的依赖装配在一起,这个时候就需要用到Spring的自动装配了。

简单来说,自动装配就是让Spring自动满足bean依赖的一种方法,在满足依赖的过程中,会在Spring应用上下文中寻找匹配某个bean需求的其他bean。为了声明要进行自动装配,我们可以借助Spring的@Autowired注解(或者@Inject注解)。

(1)创建有依赖的类

例如下面的CDPlayer类,它的构造器上添加了@Autowired注解,这表明当Spring创建CDPlayer bean的时候,会通过这个构造器来进行实例化并且会传入一个可设置给CompactDisc类型的bean。

package soundsystem;

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

/**
 *@作者:JackHisen(gwd)
 *@email:1154978352@qq.com
 *@时间:2017年7月30日 下午9:09:43
 *@version 1.0  
*/
@Component
public class CDPlayer implements MediaPlayer{
	private CompactDisc cd;
	
	//当Spring创建CDPlayer bean的时候,会通过这个构造器来进行实例化并且会传入一个可设置给CompactDisc类型的bean
	//@Auto注解不仅能够用在构造器上还能用在类的任何地方
	@Autowired 
	public CDPlayer(CompactDisc cd) {
		this.cd = cd;
	}
	
	public void play(){
		cd.play();
	}
}
需要注意的是,@Autowired注解可以在类的任何地方。另外如果没有匹配的bean,那么在应用的上下文创建的时候,Spring会抛出一个异常。为了避免异常的出现,你可以将@Autowired的required属性设置为false,这个时候Spring会尝试执行自动装配,但是如果没有装配的bean的话,SPring将会让bean处于未装配的状态。但是,把ruquired属性设置为false时,你需要谨慎对待。如果在你的代码中没有进行null检查的话,这个处于未装配状态的属性有可能会出现NullPointerException。


    (2)测试自动装配

package soundsystem;

import static org.junit.Assert.*;
import org.apache.tomcat.util.security.MD5Encoder;
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;

/**
 *@作者:JackHisen(gwd)
 *@email:1154978352@qq.com
 *@时间:2017年7月29日 下午7:33:48
 *@version 1.0  
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=CDPlayerConfig.class)
public class CDPlayerTest {
	@Autowired
	private CompactDisc compactDisc;
	
	@Autowired
	private MediaPlayer player;
	@Test
	public void cdShoudNotBeNull(){
		assertNotNull(compactDisc);
	}
	
	@Test
	public void play(){
		player.play();
	}
}


      (二)xml形式的自动装配

      1.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:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="
     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
     http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
     http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
	<context:component-scan base-package="soundsystem"/>     

</beans>

     2.测试类

package soundsystem;

import static org.junit.Assert.*;
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;

/**
 *@作者:JackHisen(gwd)
 *@email:1154978352@qq.com
 *@时间:2017年7月29日 下午7:33:48
 *@version 1.0  
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class CDPlayerTest {
	@Autowired
	private CompactDisc compactDisc;
	@Test
	public void cdShoudNotBeNull(){
		assertNotNull(compactDisc);
	}
}
其他均与java代码形式一致。


                     


阅读更多
换一批

没有更多推荐了,返回首页