《整合SSH应用开发详解》读后笔记
不同Bean创建方式有三种:
1、大多数情况下,BeanFactory使用new关键字调用构造器
2、BeanFactory调用某个类的静态工厂方法创建Bean
3、BeanFactory调用实例工厂方法创建Bean
一、使用new关键字调用构造器
使用new关键字来创建Bean实例是最常见的情形,如果采用设值注入的方式,要求类提供无参数的构造器。
BeanFactory调用默认构造器创建Bean实例,该实例是个默认的实例。所有的属性执行默认的初始化。接下来,BeanFactory会根据配置文件决定依赖关系,先实例化依赖的Bean,然后为Bean注入依赖关系,最后将一个完整的Bean示例返回给程序,该Bean示例的所有属性,已经由Spring容器完成了初始化。
调用Bean的接口和实现类:
public interface Person
{
public void useAxe();
}
Person的实现类
public class Chinese implements Person
{
private Axe axe;
public Chinese()
{
System.out.println("Spring实例化主调bean:Chinese实例...");
}
public void setAxe(Axe axe)
{
System.out.println("Spring执行依赖关系注入...");
this.axe = axe;
}
public void useAxe()
{
System.out.println(axe.chop());
}
}
下面给出Person接口依赖Bean的接口和实现类Axe
public interface Axe
{
public String chop();
}
Axe的实现类SteelAxe
public class SteelAxe implements Axe
{
public SteelAxe()
{
System.out.println("Spring实例化依赖bean:SteelAxe实例...");
}
public String chop()
{
return "钢斧砍柴真快";
}
}
Spring的配置文件如下:
<?xml version="1.0" encoding="GBK"?>
<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="steelAxe" class="lee.SteelAxe"/>
<bean id="chinese" class="lee.Chinese">
<property name="axe" ref="steelAxe"/>
</bean>
</beans>
主程序如下
public class BeanTest
{
public static void main(String[] args)throws Exception
{
//以CLASSPATH路径下的配置文件,创建ClassPathResource实例
ClassPathResource isr = new ClassPathResource("bean.xml");
//以Resource对象作为参数,创建BeanFactory的实例
XmlBeanFactory factory = new XmlBeanFactory(isr);
System.out.println("程序已经实例化BeanFactory...");
Person p = (Person)factory.getBean("chinese");
System.out.println("程序中已经完成了chinese bean的实例化...");
p.useAxe();
}
}
执行效果:
执行的结果清楚地反映了执行过程:
- 程序创建BeanFactory实例
- 调用Chinese类的默认构造器来创建默认实例
- 根据配置文件注入依赖关系,先实例化依赖Bean,然后将依赖Bean注入
- 返回一个完整的JavaBean实例
二、使用静态工厂方法创建Bean
使用静态工厂方法创建Bean实例时,class属性也是必需的,但此时class属性并不是该实例的实现类,而是静态工厂类。Spring需要知道由哪个工厂方法来创建Bean实例,使用factory-method属性来确定静态工厂方法名。Spring调用工程方法,并返回一个有效的对象。后面的过程,Spring的处理步骤与采用其他方法的创建完全一样。
下面Bean要通过factory-method指定的方法创建。注意,这个bean定义并没有bean实例的实现类,只指定静态工厂类。该工厂的工厂方法必须是静态的。如果静态工厂方法需要参数,使用<constructor-arg>元素传入即可。
Being接口
package lee;
public interface Being
{
public void testBeing();
}
下面是接口的两个实现类。
Dog类
package lee;
public class Dog implements Being
{
private String msg;
public void setMsg(String msg)
{
this.msg = msg;
}
public void testBeing()
{
System.out.println(msg + " 狗爱啃骨头");
}
}
Cat类
package lee;
public class Cat implements Being
{
private String msg;
public void setMsg(String msg)
{
this.msg = msg;
}
public void testBeing()
{
System.out.println(msg + " 猫喜欢吃老鼠");
}
}
下面的工厂包含静态方法,静态方法可返回Being实例:
package lee;
public class BeingFactory
{
public BeingFactory()
{
System.out.println("=======6");
}
public static Being getBeing(String arg)
{
if (arg.equalsIgnoreCase("dog"))
{
return new Dog();
}
else
{
return new Cat();
}
}
}
<?xml version="1.0" encoding="GBK"?>
<!-- 定义Spring配置文件的根元素,并指定Schema信息 -->
<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="dog" class="lee.BeingFactory" factory-method="getBeing">
<constructor-arg value="dog"/>
<property name="msg" value="我是狗"/>
</bean>
<bean id="cat" class="lee.BeingFactory" factory-method="getBeing">
<constructor-arg value="cat"/>
<property name="msg" value="我是猫"/>
</bean>
</beans>
如此可以看出:
1、class属性值并非是Bean的实现类,而是静态工厂类
2、必须使用factory-method指定产生实例的静态工厂方法
3、如果静态方法需要参数,数使用constructor-arg元素指定
主程序如下
public class SpringTest
{
public static void main(String[] args)throws Exception
{
//以CLASSPATH路径下的配置文件,创建ClassPathResource实例
ClassPathResource isr = new ClassPathResource("bean.xml");
//以Resource对象作为参数,创建BeanFactory的实例
XmlBeanFactory factory = new XmlBeanFactory(isr);
System.out.println("程序已经实例化BeanFactory...");
Being b1 = (Being)factory.getBean("dog");
b1.testBeing();
Being b2 = (Being)factory.getBean("cat");
b2.testBeing();
}
}
三、调用实例工厂方法创建Bean
实例工厂方法必须提供工厂实例,因此必须在配置文件中配置工厂实例。
采用实例工厂方法创建Bean的配置需要如下两个属性:
- factory-bean,该属性的值为工程的Bean的id
- factory-method,该方法负责生成Bean实例
Person接口
public interface Person
{
public String sayHello(String name);
public String sayGoodBye(String name);
}
两个Person实现类American类
public class American implements Person
{
public String sayHello(String name)
{
return name + ",Hello";
}
public String sayGoodBye(String name)
{
return name + ",Good Bye";
}
}
Chinese类
public class Chinese implements Person
{
public String sayHello(String name)
{
return name + ",您好";
}
public String sayGoodBye(String name)
{
return name + ",下次再见";
}
}
Person工厂的代码
public class PersonFactory
{
public Person getPerson(String ethnic)
{
if (ethnic.equalsIgnoreCase("chin"))
{
return new Chinese();
}
else
{
return new American();
}
}
}
Spring此时不负责创建Bean实例,而是产生Bean工厂实例。这是抽象工厂模式,Spring容器负责生成Bean实例,该Bean实例是其他实例的工厂,负责产生程序需要的Bean实例。
配置文件
<?xml version="1.0" encoding="GBK"?>
<!-- 定义Spring配置文件的根元素,并指定Schema信息 -->
<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="personFactory" class="lee.PersonFactory"/>
<bean id="chinese" factory-bean="personFactory" factory-method="getPerson">
<constructor-arg value="chin"/>
</bean>
<bean id="american" factory-bean="personFactory" factory-method="getPerson">
<constructor-arg value="ame"/>
</bean>
</beans>
主程序
public class SpringTest
{
public static void main(String[] args)throws Exception
{
//以CLASSPATH路径下的配置文件,创建ClassPathResource实例
ClassPathResource isr = new ClassPathResource("bean.xml");
//以Resource对象作为参数,创建BeanFactory的实例
XmlBeanFactory factory = new XmlBeanFactory(isr);
System.out.println("程序已经实例化BeanFactory...");
Person p1 = (Person)factory.getBean("chinese");
System.out.println(p1.sayHello("Mary"));
System.out.println(p1.sayGoodBye("Mary"));
Person p2 = (Person)factory.getBean("american");
System.out.println(p2.sayHello("Jack"));
System.out.println(p2.sayGoodBye("Jack"));
}
}
第一种方法使用较少,第二和第三中方法很类似,主要区别如下: