在Spring中如何装配Bean

来源:互联网 发布:淘宝网购物商城女装 编辑:程序博客网 时间:2024/06/01 07:59

Spring容器负责创建应用程序中的bean,并通过DI(依赖注入)来协调这些对象间的关系。但前提是开发人员告诉Spring要创建哪些bean,并且如何将它们装配在一起。
Spring提供了三种主要的装配机制:

  • 隐式的bean发现机制和自动装配
  • 在Java中进行显示配置
  • 在XML中进行显示配置

1. Spring自动化装配bean

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

  • 组件扫描(component scanning):Spring会自动发现应用上下文中所创建的bean。
  • 自动装配(autowiring):Spring自动满足bean之间的依赖。

首先你要告诉Spring要创建哪些bean,怎么告诉它呢?—–用@Component注解。

package springtest;import org.springframework.stereotype.Component;@Componentpublic class autowiringbean  {    /******/}

这个简单的注解表明该类会作为组件类,并告知Spring要为这个类创建bean。
不过,组件扫描默认是不开启的。我们需要配置一下Spring,让其扫描带有@Component注解的类,并为其创建bean。它的配置也很简单。

package springtest;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;@Configuration@ComponentScanpublic class componentbean {/***一个简单的空类即可,不需要显示的声明任何bean***/}

@Configuration注解表明这是一个配置类,@ComponentScan注解能够在Spring中开启组件扫描。
如果没有其他配置的话,@ComponentScan默认会扫描配置类所在的包以及这个包的所有子包,查找带有@Component注解的类,Spring会自动为其创建一个bean。
有些情况下,我们会把配置文件放在一个专门的包中,这时,我们需要配置一下@ComponentScan,让其扫描我们指定的包。

@ComponentScan(basePackages="包的名称")

也可以将basePackages属性设置为要扫描包的一个数组:

@ComponentScan(basePackages={"包1","包2","包3"})

这样就可以扫描多个包了。


组件扫描就简单地介绍完了,下面我们来了解下Spring自动化配置的另外一方面的内容,那就是自动装配。自动装配就是让Spring自动满足bean依赖的一种方法,在满足依赖的过程中,会在Spring应用上下文中寻找匹配某个bean需求的其他bean。

package springtest;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;@Componentpublic class autowiredtest{    @Autowired    public autowiredtest(componentbean cb){    }}

构造器上添加了@Autowired注解,这表明Spring创建autowiredtest bean的时候,会传入一个componentbean 类型的bean
@Autowired注解不仅能够用在构造器上,还可以用在类的任何需要依赖的方法上。


2. 通过JavaConfig显式装配bean

通过JavaConfig装配bean,和Spring自动化装配bean比较类似。
首先依然是常见JavaConfig配置类,JavaConfig是配置代码,这意味着它不应包含任何业务逻辑, 也不应侵入到业务逻辑代码中去,我们只能在JavaConfig声明bean

package javaconfig;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class JavaConfigtest{}

这样就我们就建立起了JavaConfig配置类。


接下来就要在JavaConfig中声明bean了。我们需要编写一个方法,这个方法会创建我们所需类型的实例,给这个方法加上@Bean注解,我们就成功声明了一个bean

@Beanpublic Bean1 setBean1(){    return new Bean1();}

@Bean注解会告诉Spring该方法会产生一个对象,该对象要注册为Spring应用上下文中的bean。Spring并不知道方法体内产生bean实例的逻辑,它只知道最终会产生一个Bean1对象。
当然,我们可以通过name属性指定一个不同的名字:

@Bean(name="firstbean"public Bean1 setBean1(){    return new Bean1();}

我们刚刚用Setter方法声明的bean1 bean是非常简单的,它并没有其他的依赖。现在我们要利用构造器来声明一个setbean2 bean,它需要依赖bean1。

@Bean(name="secondbean"public Bean2 setBean2(){    return new Bean2(setBean1());}

看起来,setBean2所需要的bean1对象是通过setBean1()获得的,但实际上并非如此。setBean1()添加了@Bean注解,Spring将会拦截所有对它的调用,并直接返回setBean1()所创建的对象,而不是每次都对其进行实际调用。

@Bean(name="secondbean"public Bean2 setBean2(){    return new Bean2(setBean1());}@Bean(name="thirdbean"public Bean3 setBean3(){    return new Bean3(setBean1());}

上面两个方法均需要调用setBean1()所创建的对象,但它们会得到相同的Bean1实例。

@Bean(name="thirdbean"public Bean3 setBean3(Bean1 b1){    return new Bean3(b1);}

通过这种方式引用其他的bean通常是最佳选择,因为它不会要求将Bean1声明到同一个配置类里,甚至不用在JavaConfig中声明。但有一点需要注意,如果Bean1在任一配置类里声明,使用上面两种引用Bean1 bean的不同方法,都会得到相同的Bean1实例。默认情况下,Spring中的bean都是单例。要想改变这种问题,除了修改配置外,我们可以这样做:

@Bean(name="thirdbean"public Bean3 setBean3(){    Bean1 b1=new Bean1();    return new Bean3(b1);}

总之,在@Bean方法体内,我们可以采用任何逻辑来产生bean实例。


3.通过XML配置Bean

“首先需要明确的是,Spring现在有了强大的自动化配置和基于Java的配置,XML不应该再是你的第一选择了”
——《Spring In Action》
当然,XML还是很强大的,我们阅读别人以前写的代码时,还是需要这一部分的基础知识的。
最为简单的Spring XML配置如下所示:

<beans xmlns="http://www.springframework.org/schema/beans"      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="        http://www.springframework.org/schema/beans         http://www.springframework.org/schema/context        http://www.springframework.org/schema/beans/spring-beans.xsd">      <!-------在这里配置------->        </beans>

接下来我们声明一个简单的<bean>

<bean class="springtest.Bean1"/>

我们可以自己设置一个名字:

<bean id="setBean1" class="springtest.Bean1"/>

Spring发现<bean>这个元素时,它将会调用Bean1的默认构造器来创建bean。
接下来,我们来了解如何借助构造器注入初始化bean。

<bean id="setBean2" class="springtest.Bean2"><constructor-arg ref="setBean1"/></bean>

Spring遇到<**bean>元素时,会创建一个Bean2实例。<constructor-arg>元素会告知Spring要讲一个ID为 setBean1的**bean引用传递到Bean2的构造器中。

然后,我们来了解一下如何将字面量注入到构造器中。

package springtest;public class Bean3{    private int id;    private String name;    public Bean3(int id,String name){    this.id=id;    this.name=name;    }}
<bean id="setBean3" class="springtest.Bean3"><constructor-arg value="1"/><constructor-arg value"小明"/></bean>

这次我们没有使用ref属性来引用其他bean,而是使用了value,通过该属性表明给定的值要以字面量的形式注入到构造器中。
除了构造器外,属性也可以注入字面量。

<bean id="setBean3" class="springtest.Bean3"><property name="id"             value="1"/><property name="name"             value="小明"/></bean>

原创粉丝点击