上一篇:(六)Spring之回顾工厂模式
spring6里程碑版本的仓库
依赖:spring context依赖、junit依赖、log4j2依赖
log4j2.xml文件放到类路径下。
Spring为Bean提供了多种实例化方式,通常包括4种方式。(也就是说在Spring中为Bean对象的创建准备了多种方案,目的是:更加灵活)
之前一直使用的就是这种方式。默认情况下,会调用Bean的无参数构造方法。
在Spring配置文件直接配置类的全路径,Spring会自动调用该类的无参数构造方法来实例化Bean。
创建一个Bean:SpringBean1类:
public class SpringBean1 {public SpringBean1() {System.out.println("Spring Bean1的无参构造方法执行");}
}
创建spring.xml配置:
测试程序:
@Testpublic void testInstantiation1(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");SpringBean1 springBean1 = applicationContext.getBean("springBean1", SpringBean1.class);System.out.println(springBean1);}
简单工厂模式实例化就是,创建一个简单工厂类,提供一个静态方法,手动实例化Bean对象,可见这个Bean是我们自己new出来的。
需要在Spring配置文件中告诉Spring框架,调用哪个类的哪个方法获取Bean。
定义一个Bean:SpringBean2类
public class SpringBean2 {public SpringBean2() {System.out.println("Spring Bean2的无参构造方法执行");}
}
定义工厂类角色:SpringBean2Factory
/*** 简单工厂模式中的工厂类角色。*/
public class SpringBean2Factory {//简单工厂模式又叫做静态工厂方法模式,有一个静态方法。public static SpringBean2 get(){//可见这个对象最终创建的时候还是我们负责new的。return new SpringBean2();}
}
spring.xml配置:
factory-method属性:配置哪个方法获取Bean。
测试程序:
@Testpublic void testInstantiation2(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");SpringBean2 springBean2 = applicationContext.getBean("springBean2", SpringBean2.class);System.out.println(springBean2);}
工厂方法模式实例化就是,创建一个简单工厂类,只是这个方法不再是静态方法,而是实例方法,手动实例化Bean对象,可见这个Bean也是我们自己new出来的。
因为是实例方法,需要在Spring配置文件中配置这个工厂的Bean,并告诉Spring框架,调用哪个类的哪个方法获取Bean。
定义一个Bean:SpringBean3类
/*** 具体产品角色*/
public class SpringBean3 {public SpringBean3() {System.out.println("Spring Bean3的无参构造方法执行");}
}
工厂角色:SpringBean3Factory类
/*** 具体工厂角色*/
public class SpringBean3Factory {//工厂方法模式里的方法是实例方法public SpringBean3 get(){//可见,创建对象还是我们直接创建的return new SpringBean3();}
}
spring.xml配置:
通过factory-bean + factory-method共同完成
因为是实例方法,需要实例化对象,所以工厂方法也需要Spring管理,需要配置bean
测试程序:
@Testpublic void testInstantiation3(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");SpringBean3 springBean3 = applicationContext.getBean("springBean3", SpringBean3.class);System.out.println(springBean3);}
前三种方式中,factory-bean是我们自定义的,factory-method也是我们自己定义的。
在Spring中,当你编写的类直接实现FactoryBean接口之后,factory-bean不需要指定了,factory-method也不需要指定了。
factory-bean会自动指向实现FactoryBean接口的类,factory-method会自动指向getObject()方法。
第四种方案实际是第三种方案的简化
定义一个Bean:SpringBean4类
public class SpringBean4 {public SpringBean4() {System.out.println("Spring Bean4的无参构造方法执行");}
}
定义一个工厂:SpringBean4FactoryBean,实现FactoryBean接口
这个工厂也是一个Bean,只不过这个Bean比较特殊,叫做工厂Bean
通过这个工厂Bean可以获取普通的Bean
FactoryBean接口有三个方法,分别是:
public interface FactoryBean {String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";@NullableT getObject() throws Exception;@NullableClass> getObjectType();default boolean isSingleton() {return true;}
}
SpringBean4FactoryBean:
public class SpringBean4FactoryBean implements FactoryBean {/*在这个方法创建Bean*/@Overridepublic SpringBean4 getObject() throws Exception {//最终也是程序员自己new的return new SpringBean4();}@Overridepublic Class> getObjectType() {return null;}/*在源码中有一个默认方法,它会告诉Spring,创建Bean是否是单例的,如果不想单例,覆盖该方法并返回false就可以这里就不在操作了,默认调用接口的默认方法*/@Overridepublic boolean isSingleton() {return FactoryBean.super.isSingleton();}
}
spring.xml配置:
测试程序:
@Testpublic void testInstantiation4(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");SpringBean4 springBean4 = applicationContext.getBean("springBean4", SpringBean4.class);System.out.println(springBean4);}
Spring IoC容器的顶级对象,BeanFactory被翻译为“Bean工厂”,在Spring的IoC容器中,“Bean工厂”负责创建Bean对象。
BeanFactory是工厂。
FactoryBean:它是一个Bean,是一个能够辅助Spring实例化其它Bean对象的一个Bean。
在Spring中,Bean可以分为两类:
java.util.Date在Spring中被当做简单类型,简单类型在注入的时候可以直接使用value属性或value标签来完成。
但我们之前已经测试过了,对于Date类型来说,采用value属性或value标签赋值的时候,对日期字符串的格式要求非常严格,必须是特殊格式的。其他格式是不会被识别的。
所以我们可以使用FactoryBean接口对Bean的创建进行增强操作。
定义一个学生类:Student
public class Student {private Date birth;public void setBirth(Date birth) {this.birth = birth;}@Overridepublic String toString() {return "Student{" +"birth=" + birth +'}';}
}
创建一个工厂Bean:DateFactoryBean类,实现FactoryBean
public class DateFactoryBean implements FactoryBean {private String strDate;public DateFactoryBean(String strDate) {this.strDate = strDate;}@Overridepublic Date getObject() throws Exception {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");Date date = sdf.parse(strDate);return date;}@Overridepublic Class> getObjectType() {return null;}
}
spring.xml配置:
测试程序:
@Testpublic void testStudentDate(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");Student student = applicationContext.getBean("student", Student.class);System.out.println(student);}