Spring
为Bean
提供了多种实例化方式,通常包括4种方式。(也就是说在Spring
中为Bean
对象的创建准备了多种方案,目的是:更加灵活)
- 第一种:通过构造方法实例化
- 第二种:通过简单工厂模式实例化
- 第三种:通过
factory-bean
实例化 - 第四种:通过
FactoryBean
接口实例化
1 通过构造方法获取
<!--Spring提供的实例化方式,第一种,在Spring配置文件中直接配置类全路径,Spring会自动调用该类的无参数构造方法来实例化Bean-->
<bean class="com.cjf.bean.SpringBean" id="bean"/>
2 通过简单工厂模式获取
public class Star {
public Star() {
System.out.println("Star的无参数构造方法执行");
}
}
//明星工厂
public class StarFactory {
public static Star get() {
//这个Star对象实际上是我们负责new的对象
return new Star();
}
}
<!---Spring提供的实例化方式,第二种:通过简单工厂桃式。你需要在Spring配置文件中告诉Spring框架,调用哪个类的哪个方法软取Bean-->
<!--factory-method 属性指定的是工厂类当中的静态方法,也就是告诉Spring框架,调用这个方法可以获取Bean-->
<bean id="star" class="com.cjf.bean.StarFactory" factory-method="get"/>
3 通过factory-bean获取
具体的Gun
public class Gun extends Mechanical{
public Gun() {
System.out.println("Gun的无参数构造方法执行");
}
}
抽象的 MechanicalFactory
,都是一种产品:机械产品
public abstract class MechanicalFactory {
protected abstract Mechanical get();
}
具体的GunFactory
public class GunFactory extends MechanicalFactory {
@Override
protected Mechanical get() {
return new Gun();
}
}
<!--Spring提供的实例化方式,第三种:通过工厂方法模式。通过factory-bean 属性 + factory-method 属性共同来完成-->
<!--告诉Spring框架,调用哪个对象 的哪个方法来获取Bean-->
<bean id="gunFactory" class="com.cjf.bean.GunFactory"/><!--GunFactory实际上就是一个FactoryBean-->
<bean id="gun" factory-bean="gunFactory" factory-method="get"/>
4 通过FactoryBean接口获取
以上的第三种方式中,factory-bean
是我们自定义的,factory-method
也是我们自己定义的。
在Spring
中,当你编写的类直接实现FactoryBean
接口之后,factory-bean
不需要指定了,factory-method
也不需要指定了。
factory-bean
会自动指向实现FactoryBean
接口的类,factory-method
会自动指向getObject()
方法。
public class PersonFactoryBean implements FactoryBean<Person> {
// PersonFactoryBean 也是一个Bean,只不过通过这个Bean比较特殊,叫做工厂Bean
@Override
public Person getObject() throws Exception {
return new Person();
}
@Override
public Class<?> getObjectType() {
return null;
}
/**
* 接口默认返回ture,表示单例的
* 如果 多例,直接修改为return false 即可
*/
@Override
public boolean isSingleton() {
return FactoryBean.super.isSingleton();
}
}
<!--Spring提供的实例化方式,第四种:通过FactoryBean接口来实现-->
<!--由于你编写的类实现了FactoryBean接口,所以这个类是一个特殊的类-->
<!--通过一个特殊的Bean: 工厂 Bean,来返回一个普通部Bean Person对象。-->
<bean id="person" class="com.cjf.bean.PersonFactoryBean"/>
5 BeanFactory和FactoryBean的区别
5.1 BeanFactory
Spring IoC
容器的顶级对象,BeanFactory
被翻译为“Bean工厂”
,在Spring
的IoC
容器中,“Bean工厂”负责创建Bean对象。
BeanFactory是工厂。
@Test
public void testCustomScope(){
//ApplicationContext applicationContext =
// new ClassPathXmlApplicationContext("spring.xml");
BeanFatory applicationContext =
new ClassPathXmlApplicationContext("spring.xml");
}
5.2 FactoryBean
FactoryBean
:它是一个Bean
,是一个能够辅助Spring实例化其它Bean
对象的一个Bean
。
在Spring
中,Bean
可以分为两类:
- 第一类:普通
Bean
- 第二类:工厂
Bean
(记住:工厂Bean
也是一种Bean
,只不过这种Bean
比较特殊,它可以辅助Spring
实例化其它Bean
对象。)
6 注入自定义Date
public class Student {
// java.util.Date 在spring当中被当做简单类型。但是简单类型的话,注入的日期字符串格式有要求。
// java.util.Date 在rSpring当中出可以被当做非简单类型。
private Date birth;
public void setBirth(Date birth) {
this.birth = birth;
}
@Override
public String toString() {
return "Student{" +
"birth=" + birth +
'}';
}
}
我们前面说过,java.util.Date
在Spring
中被当做简单类型,简单类型在注入的时候可以直接使用value
属性或value
标签来完成。但我们 之前已经测试过了,对于Date
类型来说,采用value
属性或value
标签赋值的时候,对日期字符串的格式要求非常严格,必须是这种格式的:Mon Oct 10 14:30:26 CST 2022
。其他格式是不会被识别的。如以下代码:
<bean id="student" class="com.cjf.bean.Student">
<property name="birth" value="Mon Oct 10 14:30:26 CST 2022"/>
</bean>
<!--这种方式只能获取系统当前时间,不能作为当前生日-->
<bean class="java.util.Date" id="nowTime"></bean>
<bean id="student" class="com.cjf.bean.Student">
<property name="birth" ref="nowTime"></property>
</bean>
解决
public class DateFactoryBean implements FactoryBean<Date> {
//DateFactoryBean 这个工厂协助我们Spring创建这个普通的Date
private String strDate;
public DateFactoryBean(String strDate) {
this.strDate = strDate;
}
@Override
public Date getObject() throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = sdf.parse(strDate);
return date;
}
@Override
public Class<?> getObjectType() {
return null;
}
}
<!--创建工厂Bean:DateFactoryBean,返回普通Bean:java.util.Date-->
<bean id="date" class="com.cjf.bean.DateFactoryBean" >
<constructor-arg index="0" value="2002-6-11"/>
</bean>
<bean id="student" class="com.cjf.bean.Student">
<property name="birth" ref="date"/>
</bean>