(笔记)Spring实战_装配Bean(1)_声明Bean

时间:2021-09-25 20:31:35

创建应用对象之间关联关系的传统方法(通过构造器或者查找)通常会导致结构复杂的代码,这些代码很难被复用,也很难进行单元测试。
在Spring中,对象无需自己负责查找或创建与其关联的其他对象。相反,容器负责把需要相互协作的对象引用赋予各个对象。
创建应用对象之间协作关系的行为通常被称为装配,这也是依赖注入的本质。
1.创建Spring配置
(1)传统上,Spring使用一个或多个XML文件作为配置文件,而Spring3.0还同时提供了基于Java注解的配置方式。
(2)Spring配置文件的根元素是来源于Spring beans命名空间所定义<beans>元素。

        <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.0.0.RELEASE</version>
<scope>runtime</scope>
</dependency>
<?xml version="1.0" encoding="UTF-8"?>
<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/beans/spring-beans.xsd"
>


<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>

<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>

<!-- more bean definitions go here -->

</beans>

2.声明一个简单Bean
Performer接口

package com.springinaction.springidol;

public interface Performer
{
void perform();
}

Juggler Bean

package com.springinaction.springidol;

public class Juggler implements Performer
{


private int beanBags = 3;

public Juggler()
{

}

public Juggler(int beanBags)
{
this.beanBags = beanBags;
}

public void perform()
{
System.out.println("JUGGLER " + beanBags + " BEANBAGS");
}

}

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


<bean id="duke" class="com.springinaction.springidol.Juggler" />
</beans>

加载Spring上下文(当Spring容器加载该Bean时,Spring将使用默认的构造器来实例化duke Bean)

        ApplicationContext ctx = new ClassPathXmlApplicationContext(
"com/springinaction/springidol/spring-idol.xml");
Performer performer = (Performer)ctx.getBean("duke");
performer.perform();

3.通过构造器注入

    <bean id="duke" class="com.springinaction.springidol.Juggler">
<constructor-arg value="15" />
</bean>

通过构造器注入对象引用
Poem接口

package com.springinaction.springidol;

public interface Poem
{
void recite();
}
package com.springinaction.springidol;

public class Sonnet29 implements Poem
{


private static String[] LINES = {"Don't aim for success if you really want it,",
"just stick to what you love and believe in,", "and it will come naturally."};

public Sonnet29()
{

}

public void recite()
{
for (int i = 0; i < LINES.length; i++ )
{
System.out.println(LINES[i]);
}
}

}

会朗诵诗歌的杂技师

package com.springinaction.springidol;

public class PoeticJuggler extends Juggler
{

private Poem poem;

public PoeticJuggler(Poem poem)
{
super();
this.poem = poem;
}

public PoeticJuggler(int beanBags, Poem poem)
{
super(beanBags);
this.poem = poem;
}

public void perform()
{
super.perform();
System.out.println("While reciting...");
poem.recite();
}
}

spring-idol.xml

    <bean id="sonnet29" class="com.springinaction.springidol.Sonnet29" />

<bean id="poeticDuke" class="com.springinaction.springidol.PoeticJuggler">
<constructor-arg value="15" />
<constructor-arg ref="sonnet29" />
</bean>

通过工厂方法创建Bean
要装配的对象需要通过静态方法来创建(单例类)

package com.springinaction.springidol;

public class Stage
{

private Stage()
{

}

private static class StageSingletonHolder
{
static Stage instance = new Stage();
}

public static Stage getInstance()
{
return StageSingletonHolder.instance;
}
}

spring-idol.xml

    <bean id="theStage" class="com.springinaction.springidol.Stage"
factory-method="getInstance" />

4.Bean的作用域
所有的Spring Bean默认都是单例。
为了让Spring在每次请求时都为Bean产生一个新的实例,我们只需要配置Bean的scope属性为prototype即可。

作用域 定义
singleton 在每一个Spring容器中,一个Bean定义只有一个对象实例(默认)
prototype 允许Bean的定义可以被实例化任意次(每次调用都创建一个实例)
request 在一次HTTP请求中,每个Bean定义对应一个实例。该作用域仅在基于Web的Spring上下文中才有效
session 在一个HTTP Session中,每个Bean定义对应一个实例。该作用域仅在基于Web的Spring上下文中才有效
global-session 在一个全局HTTP Session中,每个Bean定义对应一个实例。该作用域仅在Portlet上下文中才有效

Spring的单例Bean只能保证在每个应用上下文中只有一个Bean的实例。没有人可以阻止你使用传统的方式实例化同一个Bean,或者你甚至可以定义几个<bean>声明来实例化同一个Bean。
5.初始化和销毁Bean
为Bean定义初始化和销毁操作,只需要使用init-method和destroy-method参数来配置<bean>元素。init-method属性指定了在初始化Bean时要调用的方法。类似的,destroy-method属性指定了Bean从容器移除之前要调用的方法。

package com.springinaction.springidol;

public class Auditorium
{

public void turnOnLights()
{
// ...
}

public void turnOffLights()
{
// ...
}
}
    <bean id="auditorium" class="com.springinaction.springidol.Auditorium"
init-method="turnOnLights" destroy-method="turnOffLights" />

为Bean定义初始化和销毁方法的另一种可选方式是,让Bean实现Spring的InitializingBean和DisposableBean接口。Spring容器以特殊的方式对待实现这两个接口的Bean,允许它们进入Bean的生命周期。InitializingBean声明了一个afterPropertiesSet()方法作为初始化方法。而DisposableBean声明了一个destroy()方法,该方法在Bean从应用上下文移除时会被调用。使用这些生命周期接口的最大好处就是Spring能够自动检测实现了这些接口的Bean,而无需额外的配置。实现这些接口的缺点是Bean与Spring的API产生了耦合。

package com.springinaction.springidol;


import org.springframework.beans.factory.InitializingBean;


public class Auditoriums implements InitializingBean
{


public void afterPropertiesSet()
throws Exception
{
// ...
}

}
    <bean id="auditoriums" class="com.springinaction.springidol.Auditoriums" />

default-init-method属性为应用上下文中所有的Bean设置了共同的初始化方法。 default-destroy-method属性为应用上下文中所有的Bean设置了共同的销毁方法。
spring-idol.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/beans/spring-beans.xsd"

default-init-method="turnOnLights" default-destroy-method="turnOffLights">
<bean id="auditoriumss" class="com.springinaction.springidol.Auditoriumss" />
package com.springinaction.springidol;

public class Auditoriumss
{
public void turnOnLights()
{
// ...
}

}

test result

    @Test
public void test4()
{
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"com/springinaction/springidol/spring-idol.xml");
}
------------------------------
Auditorium turn on lights.
Auditoriums initial.
Auditoriumss turn on lights.