淘先锋技术网

首页 1 2 3 4 5 6 7
  • bean的常见三种装配

1.在XML中显示配置

2.在Java中进行显示配置

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

  • 自动化装配Bean

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

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

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

(1)创建可被发现的bean

其中的@Component注解,表明这个类为组件类,并且告诉Spring为这个类创建bean。

package soundsystem;

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";
	
	@Override
	public void play() {
		System.out.println("Playing " + title + " by " + artist);
	}

}

因为组件默认是不启用的,因此必须显示配置Spring,从而命其去寻找带有@Component注解的类,并为其创建bean。

@ComponentScan注解是启用组件扫描,其默认扫描与配置类相同的包及其所有的子包,查找带有@Component注解的类。

package soundsystem;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class CDPlayerConfig {

}

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:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="
  http://www.springframework.org/schema/beans 
  http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  http://www.springframework.org/schema/tx 
  http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
  http://www.springframework.org/schema/aop 
  http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
  http://www.springframework.org/schema/context 
  http://www.springframework.org/schema/aop/spring-context-2.5.xsd">
  <!-- 组件扫描 -->
  <context:component-scan base-package="soundsystem" />
  
</beans>

测试组件能够扫描CompactDisc类

在下面的测试类中使用SpringJUnit4ClassRunner,是为了方便在测试开始的时候自动创建Spring的应用上下文。注解@ContextConfiguration会告诉Spring需要在CDPlayerConfig中加载配置。因为CDPlayerConfig包含了@ComponentScan,因此最终的应用上下文应该包括CompactDiscbean.

@Autowrited注解,是为了将CompactDiscbean注入到测试代码中。


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;



@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=CDPlayerConfig.class)
public class CDPlayerTest {
	@Autowired
	private CompactDisc cd;
	
	@Test
	public void cdShouldNotBeNull() {
		assertNotNull(cd);
	}
}

(2)位组件扫描的bean命令(个人推荐使用)

Spring会根据类名为其指定一个bean的ID,就是讲类的首字母变为小写。

如果希望自己指定bean的Id。则需要如下这样:lonelyHearsClub为其bean的ID

@Component("lonelyHearsClub")
public class SgtPeppers implements CompactDisc{
}
还有一种如下所示,使用Named。

import javax.inject.Named;
@Named("lonelyHearsClub")
public class SgtPeppers implements CompactDisc{
}

(3)设置组件扫描的基础包

package soundsystem;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("soundsystem")
/***
 * 或者@ComponentScan(basePackages="soundsystem")
 * 如果是多个基础包
 * @ComponentScan(basePackages={"soundsystem","video"})
 */
public class CDPlayerConfig {

}

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

package soundsystem;

import javax.inject.Inject;

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

@Component
public class CDPlayer implements MediaPlayer{

	private CompactDisc cd;
	
	/**
	 * 
	 * 构造器注解
	 * 或者采取@Inject注解如set方法注解一样。Autowired与Inject并没有多大的区别
	 * 异常:
	 * 如果没有匹配的bean,那么在Spring应用上下文创建的时候,Spring会抛出一个异常。
	 * 此时可以讲@Autowired的required属性设置为false。如:@Autowired(required=false)。
	 * 但是此时必须在代码中支出null检查。否则会抛出NullPointerException.
	 */
	@Autowired
	public CDPlayer(CompactDisc cd) {
		this.cd = cd;
	}
	
	/**
	 * Set方法注解
	 * @param cd
	 */
	@Inject
	public void setCompactDisc(CompactDisc cd) {
		this.cd = cd;
	}
	

	@Override
	public void play() {
		// TODO Auto-generated method stub
		
	}

}

(5)验证自动装配

package soundsystem;

import static org.junit.Assert.*;

import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.StandardOutputStreamLog;
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;



@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=CDPlayerConfig.class)
public class CDPlayerTest {
	@Rule
	public final StandardOutputStreamLog log = new StandardOutputStreamLog();
	
	@Autowired
	private MediaPlayer player;
	
	@Autowired
	private CompactDisc cd;
	
	@Test
	public void cdShouldNotBeNull() {
		assertNotNull(cd);
	}
	
	@Test
	public void play() {
		player.play();
		assertEquals("Playing Sgt", log.getLog());
	}
}

  • 通过Java代码装配bean

因为要明确的将第三方库中的组件装配到自己的应用中,就需要显示的配置。不能使用自动化的配置方案。显示的有两种配置方案:Java和XML。

(1)声明简单的bean

package javaConfig;

import org.springframework.context.annotation.Bean;

public class CDPlayerConfig {
	
	/**
	 * @Bean注解会告诉Spring这个方法会返回一个对象。该对象要注册为Spring应用上下文中的bean.
	 * bean的ID与带有@Bean注解的方法名一样。本例中名字是sgtPeppers。
	 * 如果要设置不同的名字,通过name属性指定一个不同的名字。如@Bean(name="lonlyHeartsClubBand")
	 * @return
	 */
	@Bean
	public CompactDisc sgtPeppers() {
		return new SgtPeppers();
	}
}

(2)借助JavaConfig实现注入

CDPlayer.java

package javaConfig;
import org.springframework.beans.factory.annotation.Autowired;

public class CDPlayer implements MediaPlayer {
  private CompactDisc cd;

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

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

}
CDPlayerConfig.java

package javaConfig;

import org.springframework.context.annotation.Bean;

public class CDPlayerConfig {

	@Bean
	public CompactDisc sgtPeppers() {
		return new SgtPeppers();
	}
	
	@Bean
	public CDPlayer cdPlayer() {
		return new CDPlayer(sgtPeppers());
	}
}

默认情况下,Sping中的Bean都是单例的,并没有为第二个CDPlayer创建相同的SgtPeppers实例。因此,Spring会拦截对sgtPeppers()的调用并确保返回的是Spring所创建的bean。sgtPeppers()方法添加了@Bean,Spring将会拦截所有对它的调用,并确保直接返回该方法所创建的bean,而不是每次都对其进行实际的调用。

以传递参数的形式进行创建

	/**
	 * 传参的方式进行,让方法体按照合适的方式调用它。而不需要明确引用CompactDisc的@Bean方法
	 * @param cd
	 * @return
	 */
	@Bean
	public CDPlayer cdPlayer(CompactDisc cd) {
		return new CDPlayer(cd);
	}

以set方法的形式进行传递

/**
	 * set注入的形式
	 * @param cd
	 * @return
	 */
	@Bean
	public CDPlayer cdPlayer(CompactDisc cd) {
		CDPlayer cdPlayer = new CDPlayer(cd);
		cdPlayer.setCDPlayer(cd);
		return new CDPlayer(cd);
	}

  • 通过XML装配bean

(1)通过构造器注入的形式装配

java类

package xmlCongfig.collections;

import java.util.List;

import soundsystem.CompactDisc;

public class BlankDisc implements CompactDisc {

  private String title;
  private String artist;
  private List<String> tracks;

  public BlankDisc(String title, String artist, List<String> tracks) {
    this.title = title;
    this.artist = artist;
    this.tracks = tracks;
  }

  public void play() {
    System.out.println("Playing " + title + " by " + artist);
    for (String track : tracks) {
      System.out.println("-Track: " + track);
    }
  }

}

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"
	xmlns:c="http://www.springframework.org/schema/c"
	xsi:schemaLocation="
  http://www.springframework.org/schema/beans 
  http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  http://www.springframework.org/schema/context 
  http://www.springframework.org/schema/context/spring-context-2.5.xsd">
	<!--******************** 构造器类型的DI方式 ******************************* -->
	<bean id="compactDisc" class="xmlCongfig.BlankDisc.java">
		<!-- 向构造器中传递参数 -->
		<constructor-arg value="sgtssss" />
		<constructor-arg value="The tsttts" />
		<!-- conlection类型的数据传递 -->
		<constructor-arg>
			<list>
				<value>12312</value>
				<value>weqe</value>
				<value>sda</value>
				<value>12</value>
				<value>das</value>
				<value>21312</value>
			</list>
		</constructor-arg>
	</bean>
	<!-- 使用<constructor-arg>标签的形式 -->
	<bean id="cdPlayer" class="javaConfig.CDPlayer">
		<constructor-arg ref="compactDisc" />
	</bean>
	<!-- 使用c-命名空前来声明构造器的参数。c:为c-命名空间前缀。cd:构造器参数名。-ref:呼入bean的引用。 compactDisc:要注入的beanID -->
	<!-- <bean id="cdPlayer" class="javaConfig.CDPlayer" c:cd-ref="compactDisc" 
		/> -->
</beans>
(2)通过xml的形式进行装配

java类

package soundsystem.properties;
import org.springframework.beans.factory.annotation.Autowired;

import soundsystem.CompactDisc;
import soundsystem.MediaPlayer;

public class CDPlayer implements MediaPlayer {
  private CompactDisc compactDisc;

  @Autowired
  public void setCompactDisc(CompactDisc compactDisc) {
    this.compactDisc = compactDisc;
  }

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

}

package soundsystem.properties;

import java.util.List;

import soundsystem.CompactDisc;

public class BlankDisc implements CompactDisc {

  private String title;
  private String artist;
  private List<String> tracks;

  public void setTitle(String title) {
    this.title = title;
  }

  public void setArtist(String artist) {
    this.artist = artist;
  }

  public void setTracks(List<String> tracks) {
    this.tracks = tracks;
  }

  public void play() {
    System.out.println("Playing " + title + " by " + artist);
    for (String track : tracks) {
      System.out.println("-Track: " + track);
    }
  }

}

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"
	xmlns:c="http://www.springframework.org/schema/c"
	xsi:schemaLocation="
  http://www.springframework.org/schema/beans 
  http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  http://www.springframework.org/schema/context 
  http://www.springframework.org/schema/context/spring-context-2.5.xsd">

	<!--******************** set类型的DI方式 ******************************* -->
	<bean id="compactDisc" class="xmlCongfig.BlankDisc">
<!--参数的传递-->
 <property name="title" value="sda" />
		<property name="srts" value="23432" />
		<property name="tracks">
			<list>
				<value>2134234</value>
				<value>6</value>
				<value>456</value>
				<value>23453</value>
				<value>652</value>
			</list>
		</property>
	</bean>
	<bean id="cdPlayer" class="xmlCongfig.CDPlayer">
		<property name="compactDisc" ref="compactDisc" />
	</bean>
</beans>

  • 导入和混合配置

(1)强两个分开的Configuration类导入到总的Configuration

定义BlankDis的Config类CDConfig。

CDConfig.java

package xmlCongfig;

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

@Configuration
public class CDConfig {
	@Bean
	public CompactDisc compactDisc() {
		return new SgtPeppers();
	}
}
定义CDPlayer的Configl类CDPLayerConfig

package soundsystem;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class CDPlayerConfig {
  
  @Bean
  public CDPlayer cdPlayer(CompactDisc compactDisc) {
    return new CDPlayer(compactDisc);
  }

}

将两个Configuration类同时导入到总的SoundSystemConfig的类中

package xmlCongfig;

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

@Configuration
@Import({CDConfig.class,CDPlayerConfig.class})
public class SoundSystemConfig {

}

假如BlankDisc的配置被写在了同目录下的cd-config.xml文件中,则SoundSystemConfig类的配置如下所示。

package xmlCongfig;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportResource;

@Configuration
@Import(CDPlayerConfig.class)
@ImportResource("classpath:cd-config.xml")
public class SoundSystemConfig {

}
两个bean。一个是配置在JavaConfig中的CDPlayer以及配置在XML中BlankDiSC都会被加载都SPring容器之中。