Spring之创建Bean的方式

Bean有别于传统的JavaBean,任何应用组件都可以作为Bean,接下来讲述的是Spring中创建Bean的方式。

1.调用构造器创建Bean

使用构造器来创建Bean是最常见的情况,如果是构造注入,则通过配置构造函数来实现创建Bean,如果是设值注入,Spring底层会调用Bean类的无参数构造器来创建实例。以下讲述的是设值注入。
以下是需要的接口
package impl;


public interface Axe {
	public String chop();

}
package impl;

public interface Creature {

	public void useTool();
}
package impl;

public interface Metal {
	public String make();

}
以下是三个接口相应的实现类:

package impl.handle;

import impl.Axe;

public class StealAxe implements Axe {

	@Override
	public String chop() {
		// TODO Auto-generated method stub
		return "使用斧头砍柴";
	}

}
package impl.handle;

import impl.Axe;
import impl.Creature;
import impl.Metal;
public class Person implements Creature
{
	private Axe axe;
	private Metal metal;
	// 设值注入所需的setter方法
	public void setMetal(Metal metal)
	{
		this.metal=metal;
		
	}
	public void setAxe(Axe axe)
	{
		this.axe=axe;
	}
	public void useTool()
	{
		System.out.println("我打算去砍点柴火!");
		// 调用axe的chop()方法,
		// 表明Person对象依赖于axe对象
		System.out.println(metal.make());
		System.out.println(axe.chop());
	}
}
package impl.handle;

import impl.Metal;

public class Steal implements Metal {
	public String make()
	{
		return "使用铁做斧头";
	}

}
根据需要的功能,编写工具类

package test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import impl.handle.*;
import impl.*
;public class BeanTest
{
	public static void main(String[] args)throws Exception
	{
		// 以类加载路径下的beans.xml文件创建Spring容器
		ApplicationContext ctx = new
			ClassPathXmlApplicationContext("beans.xml");    // ①
		// 加载类的时候需要加载接口,从而真正实现面向接口编程。
		Creature c=(Creature)ctx.getBean("person", Creature.class);
		c.useTool();
	}
}
然后对Beans.xml文件进行配置

<?xml version="1.0" encoding="GBK"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://www.springframework.org/schema/beans"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
	<!-- 配置名为person的Bean,其实现类是org.crazyit.app.service.Person类 -->
	<bean id="person" class="impl.handle.Person">
		<property name="metal" ref="steal"/>
		<property name="axe" ref="stealAxe"/>
	</bean>
	<bean id="steal" class="impl.handle.Steal"/>
	<bean id="stealAxe" class="impl.handle.StealAxe"/>
</beans>

以上是设值注入,所以使用的是Spring底层调用Bean类的无参数构造器来创建实例的。这里的Bean类是指Steal类和StealAxe类。

2.调用静态工厂方法创建Bean

所谓静态工厂方法就是建立一个工厂类,工厂类有个静态工厂方法,让产品的实例化在工厂类的静态工厂方法中进行,让整个过程都面向接口编程。并且在配置beans.xml文件略有不同。通过以下例子进行详细讲述。
首先先定义一个接口,该接口的实例就是在静态工厂方法中生产的。

package handle;

public interface Being {
	public void testBeing();

}
以下两个类Dog类和Cat类便是以上接口的实现类。

package handle.impl;

import handle.Being;

public class Dog implements Being {
	
	private String msg;
	public void setMsg(String msg)
	{
		this.msg=msg;
	}
	//实现接口中的testBeing()方法
	@Override
	public void testBeing() {
		// TODO Auto-generated method stub
		System.out.println(msg+",狗爱啃骨头");

	}

}
package handle.impl;

import handle.Being;

public class Cat implements Being {

	private String msg;
	public void setMsg(String msg)
	{
		this.msg=msg;
	}
	@Override
	public void testBeing() {
		// TODO Auto-generated method stub
		System.out.println(msg+",猫喜欢吃老鼠");

	}

}

相应的类都准备就绪,产品的原料都到了,就等着工厂进行集中生产,于是我们应当建立一个工厂类,然后在工厂类中建立一个静态工厂方法,将所有的类进行相应的实例化。
package factory;
import handle.*;
import handle.impl.*;
public class BeingFactory {
	//返回Being实例的静态工厂方法
	public static Being getBeing(String arg)
	{
		//调用次静态方法的参数是dog,则返回Dog实例
		if(arg.equalsIgnoreCase("dog"))
		{
			return new Dog();
		}
		else
		{
			return new Cat();
		}
	}

}
以上便是一个工厂类BeingFactory,而工厂类有个静态方法是getBeing(String arg),而arg是传入的参数,相当于外界需要什么类的实例,则工厂方法就实例化什么类。
以下是beans.xml的配置内容:
<?xml version="1.0" encoding="GBK"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://www.springframework.org/schema/beans"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
	<bean id="dog" class="factory.BeingFactory" factory-method="getBeing">
		<constructor-arg value="dog"/>
		<property name="msg" value="我是狗"/>
	</bean>
	<bean id="cat" class="factory.BeingFactory" factory-method="getBeing">
		<constructor-arg value="cat"/>
		<property name="msg" value="我是猫"/>
	</bean>
</beans>
可以看出<bean.../>子元素中id还是指实例名,作为标识作用,而class与构造器创建Bean的有所不同,构造器创建Bean的class指的是id对应的需要实例的类名,而静态工厂方法创建Bean中的class是工厂类的类名(包含包路径),另外不同的是还多了factory-method元素,是指工厂类中的静态工厂方法名,如上便是getBeing。而静态方法需要的相应的参数,则使用<constructor-arg.../>传入,而传入的参数还需要参数,则由<property.../>元素传入。
接下来是建立工具类:
package test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import handle.*;
public class SpringTest {

	public static void main(String[] args)
	{
		// 以类加载路径下的beans.xml文件创建Spring容器
		ApplicationContext ctx = new
			ClassPathXmlApplicationContext("beans.xml"); 
		Being b1=ctx.getBean("dog", Being.class);
		b1.testBeing();
		Being b2=ctx.getBean("cat", Being.class);
		b2.testBeing();
	}
}
运行工具类之后,得到如下结果:

我是狗,狗爱啃骨头
我是猫,猫喜欢吃老鼠
以上便是静态工厂方法创建Bean的示例。与构造器创建Bean最大的不同便是使用了工厂方法集中实例化,还有就是配置中<bean.../>元素中的class的不同。

3.调用实例工厂方法创建Bean

调用实例工厂方法与调用静态工厂方法类似,只是工厂类中的工厂方法有无static之分,以及配置上内容稍有差异,为便于区分,仍然使用调用静态工厂方法的示例。

先是产品接口:
package handle;

public interface Being {
	public void testBeing();

}
然后相应的产品类:

package handle.impl;

import handle.Being;

public class Dog implements Being {
	
	private String msg;
	public void setMsg(String msg)
	{
		this.msg=msg;
	}
	//实现接口中的testBeing()方法
	@Override
	public void testBeing() {
		// TODO Auto-generated method stub
		System.out.println(msg+",狗爱啃骨头");

	}

}
package handle.impl;

import handle.Being;

public class Cat implements Being {

	private String msg;
	public void setMsg(String msg)
	{
		this.msg=msg;
	}
	@Override
	public void testBeing() {
		// TODO Auto-generated method stub
		System.out.println(msg+",猫喜欢吃老鼠");

	}

}
建立工厂类,可以看到工厂类中的工厂方法没有static。

package factory;
import handle.*;
import handle.impl.*;
public class BeingFactory {
	//返回Being实例的静态工厂方法
	public Being getBeing(String arg)
	{
		//调用次静态方法的参数是dog,则返回Dog实例
		if(arg.equalsIgnoreCase("dog"))
		{
			return new Dog();
		}
		else
		{
			return new Cat();
		}
	}

}
以下是beans.xml的配置:
<?xml version="1.0" encoding="GBK"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://www.springframework.org/schema/beans"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
	<!-- 配置名为beingFactory的工厂类Bean,其实现类是factory.beingFactory类 -->
	<bean id="beingFactory" class="factory.BeingFactory"/>
	<!-- 下面配置驱动Spring调用beingFactory Bean的getBeing()方法来创建Bean,该Bean元素包含地constructor-arg元素用于为工厂方法指定参数
	BeingFactory bf=container.get("beingFactory");//container代表Spring容器
	dog=bf.getBeing("dog");-->
	<bean id="dog" factory-bean="beingFactory" factory-method="getBeing">
		<constructor-arg value="dog"/>
		<property name="msg" value="我是狗"/>
	</bean>
	<bean id="cat" factory-bean="beingFactory" factory-method="getBeing">
		<constructor-arg value="cat"/>
		<property name="msg" value="我是猫"/>
	</bean>
</beans>
从以上配置内容可以看出,先对工厂类进行配置,工厂类的配置跟调用构造器的配置类似,主要是id与class,然后进行配置产品实例,id仍然是产品名,但是没有class,而是用factory-bean取代,factory-bean就是前面已经配置好的工厂类的id,factory-method则是工厂方法,其余都同调用静态工厂方法。主要区别在于先进行工厂类的Bean配置,然后配置产品Bean实例时,class用factory-bean取代。
最后建立工具类:

package test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import handle.*;
public class SpringTest {

	public static void main(String[] args)
	{
		// 以类加载路径下的beans.xml文件创建Spring容器
		ApplicationContext ctx = new
			ClassPathXmlApplicationContext("beans.xml"); 
		Being b1=ctx.getBean("dog", Being.class);
		b1.testBeing();
		Being b2=ctx.getBean("cat", Being.class);
		b2.testBeing();
	}
}
运行工具类,得到如下结果:
我是狗,狗爱啃骨头
我是猫,猫喜欢吃老鼠
综上所述,创建Bean的三种方式,首先使用工厂方法创建Bean与调用构造器创建Bean的区别在于:1.前者使用了工厂方法便于集中管理,而后者只是将Bean实例作为参数传入其它类。2.配置beans.xml的内容略有不同。
而调用静态方法创建Bean与调用实例工厂方法创建Bean的区别:
1.配置实例工厂方法创建Bean,必须将实例工厂配置成Bean实例,而配置静态工厂方法创建Bean,无须配置工厂Bean
2.配置实例工厂方法创建Bean,必须使用factory-bean属性确定工厂Bean,而配置静态工厂方法创建Bean,使用class元素确定静态工厂类。
相同之处:
1.都需要factory-method属性确定Bean实例的工厂方法
2.工厂方法需要参数,都使用<constructor-arg.../>元素指定参数值
3.普通的设值注入,都使用<property.../>元素确定参数值







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值