spring的三种主要的装配机制

好久不见. 提交于 2020-11-14 11:25:01

本文中使用一个接口类UserInterface以及接口的实现类UserInterfaceImpl,调用接口UserInterface的UserCall类来做示例。

package com.springbean;

public interface UserInterface {
	void userMethod();
}
package com.springbean.impl;

import com.springbean.UserInterface;

public class UserInterfaceImpl implements UserInterface{

	public void userMethod() {
		System.out.println("UserInterfaceImpl - userMethod()");
	}

}
package com.springbean;

import java.util.List;

public class UserCall {

	private UserInterface ui;

	private String username;

	private List<String> tags;

	/**
	 * getter and setter
	 */
}

在下面,我们即将为UserCall注入一个UserInterface的实现类,一个字符常量以及一个集合

一 xml中配置

在spring的xml配置文件中配置装配信息,配置组件bean的话只需要使用<bean>标签即可。

<bean id="userInterface" class="com.springbean.impl.UserInterfaceImpl" />

假如配置的bean下面也有需要注入的参数,比如为userCall注入userInterface的实现类和其他参数那么可以使用两种方式注入参数。

  1. 使用构造器注入。

    可以直接使用<constructor-arg>标签。

    <util:list id="tagsList">
    	<value>cool</value>
    	<value>nice</value>
    </util:list>
    
    <bean id="userCall" class="com.springbean.UserCall">
    	<constructor-arg name="ui" ref="userInterface"/>
    	<constructor-arg name="username" value="test"/>
    	<constructor-arg name="tags" ref="tagsList"></constructor-arg>
    </bean>
    

    引用另外的bean时使用ref,字符串常量则使用value。

    也可以使用c-命名空间,在c-命名空间和模式声明之后

    <beans ...... xmlns:c="http://www.springframework.org/schema/c"
     ...... >
    </beans>
    
    <bean id="userCall" class="com.springbean.UserCall" c:ui-ref="userInterface" c:username="test" c:tags="tagsList" />
    

    使用c-命名空间可以明显缩短配置长度。

    不过使用构造器注入的时候必须在类中添加对应的构造方法才能有效,因为注入时调用的是类的构造方法,比如userCall类中调用

    public UserCall(UserInterface ui, String username, List<String> tags){
    	this.ui = ui;
    	this.username = username;
    	this.tags = tags;
    }
    
  2. 使用属性注入

    直接使用<property>标签

    <bean id="userCall" class="com.springbean.UserCall">
    	<property name="ui" ref="userInterface" />
    	<property name="username" value="test" />
    	<property name="tags" value="tagsList" />
    </bean>
    

    使用p-命名空间

    <bean id="userCall" class="com.springbean.UserCall" p:ui-ref="userInterface" p:username="test" p:tags="tagsList" />
    

    属性注入调用的是setter方法,所以类中要有相应的setter方法。

二 在Java中显式配置

使用**@Configuration可以将java的类文件声明成spring的配置类,使用@Bean来声明方法的返回对象要注册为spring的bean对象。而且一般的方法名即为id名,当然也可以为bean指定名称,通过其@Bean注解的name**属性。而当bean中需要注入其他参数或者引用时,将其作为方法的参数即可,Spring会帮你注入这些引用,如下面的userCall方法。

package com.springbean;

import java.util.ArrayList;
import java.util.List;

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

import com.springbean.impl.UserInterfaceImpl;

@Configuration
public class SpringConfig {

	@Bean
	public String username(){
		return "test";
	}

	@Bean
	public List<String> tags(){
		List<String> tags = new ArrayList<String>();
		tags.add("cool");
		tags.add("nice");
		return tags;
	}

	@Bean
	public UserInterface userInterface(){
		return new UserInterfaceImpl();
	}

	@Bean
	public UserCall userCall(UserInterface userInterface, String username, List<String> tags){
		UserCall uc = new UserCall();
		uc.setUi(userInterface);
		uc.setUsername(username);
		uc.setTags(tags);
		return uc;
	}
}

使用java类做配置类使用时同样和xml文件一样需要加载,比如测试时在上下文配置信息**@ContextConfiguration**上填上配置类。

package com.springbean.demo;

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;

import com.springbean.UserCall;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=com.springbean.SpringConfig.class)
public class MainTest {

	@Autowired
	private UserCall uc;

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

}

三 自动化装配bean

要实现自动化装配的关键之一在于能让Spring知道有哪些组件存在,你需要手动打开Spring的组件扫描。可以在Spring的xml文件中打开,使用

<context:component-scan base-package="com.springbean.*"/>

当然前提是引入了Spring context的命名空间,上面的示例还指定了扫描的包的位置。也可以在java的配置类中启用组件扫描。

package com.springbean;

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

@Configuration
@ComponentScan
public class SpringConfig {

}

注解@ComponentScan指定了spring将扫描这个配置类所在的包及其子包下面的所有类。有了组件扫描后,所有被注解@Component或者@Named注解的类都将被识别为组件类,这两个注解都可以声明组件的名字。

package com.springbean.impl;

import org.springframework.stereotype.Component;
import javax.inject.Named;

import com.springbean.UserInterface;

//@Component
@Named("userInterface")
public class UserInterfaceImpl implements UserInterface{

	public void userMethod() {
		System.out.println("UserInterfaceImpl - userMethod()");
	}

}

使用注解**@Autowired**可以方便的将配置好的bean注入到想要注入的位置。

四 混合使用

无论采用何种方式去声明一个bean,在spring中都可以任意的使用到任何地方去。自动装配与其他两种方式的配合使用最简单,只需要开启组件扫描就行了。

以Java Config为主,在java的配置类中使用xml配置

@Configuration
@ImportResource("classpath:springbean.xml")
public class SpringConfig {
	......
}

以xml配置为主,在xml配置中使用java Config,使用<bean>将其导入

<bean class="com.springbean.SpringConfig" />
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!