《整合SSH应用开发详解》读后笔记
不同Bean创建方式有三种:
1、大多数情况下,BeanFactory使用new关键字调用构造器
2、BeanFactory调用某个类的静态工厂方法创建Bean
3、BeanFactory调用实例工厂方法创建Bean
使用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(); } }
执行的结果清楚地反映了执行过程:
使用静态工厂方法创建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 + " 狗爱啃骨头"); } }
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 + " 猫喜欢吃老鼠"); } }
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的配置需要如下两个属性:
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"; } }
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(); } } }
配置文件
<?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")); } }
第一种方法使用较少,第二和第三中方法很类似,主要区别如下: