1. Spring中的BeanFactory
BeanFactory是一个接口,表示它是一个工厂,负责生产和管理bean。在Spring中,BeanFactory是IOC容器的核心接口,定义了管理Bean的通用方法,如 getBean
和 containsBean
。
BeanFactory与IOC容器
DefaultListableBeanFactory类图
BeanFactory只是个接口,并不是IOC容器的具体实现。Spring提供了多种实现,如 DefaultListableBeanFactory
、XmlBeanFactory
、ApplicationContext
等。
ApplicationContext
ApplicationContext
是Spring框架中最常用的IoC容器,是BeanFactory的子接口,提供了更丰富的功能和更强的扩展性。
ApplicationContext的子类
ClassPathXmlApplicationContext
:基于XML配置文件的ApplicationContext实现类,可以加载类路径下的XML配置文件。FileSystemXmlApplicationContext
:基于XML配置文件的ApplicationContext实现类,可以加载文件系统中的XML配置文件。AnnotationConfigApplicationContext
:基于Java注解的ApplicationContext实现类,可以通过Java配置类来管理Bean实例。WebApplicationContext
:适用于Web应用场景的ApplicationContext子接口,提供了更丰富的Web应用支持。
这些ApplicationContext子类都实现了ApplicationContext接口,提供了不同的功能和扩展性,可以根据具体的应用场景选择合适的ApplicationContext子类来管理Bean实例。
BeanFactory的使用示例
// User.java
public class User {
private int id;
private String name;
private Friends friends;
public User() { }
public User(Friends friends) {
this.friends = friends;
}
// getters and setters...
}
// Friends.java
public class Friends {
private List<String> names;
public Friends() { }
public List<String> getNames() {
return names;
}
public void setNames(List<String> names) {
this.names = names;
}
}
配置文件(bean.xml)
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-4.2.xsd">
<bean id="User" class="com.example.factory.User">
<property name="friends" ref="UserFriends" />
</bean>
<bean id="UserFriends" class="com.example.factory.Friends">
<property name="names">
<list>
<value>LiLi</value>
<value>LuLu</value>
</list>
</property>
</bean>
</beans>
测试类
public class SpringFactoryTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
User user = ctx.getBean("User", User.class);
List<String> names = user.getFriends().getNames();
for (String name : names) {
System.out.println("FriendName: " + name);
}
ctx.close();
}
}
2. Spring中的FactoryBean
FactoryBean 是一个工厂Bean,相当于将工厂类放到了Spring中管理。当获取此Bean时返回的是该工厂生成的Bean。
FactoryBean通常用于创建比较复杂的bean。对于一般的bean,可以直接用XML配置;但如果一个bean的创建过程中涉及到很多其他bean和复杂的逻辑,用XML配置可能比较困难,这时可以考虑用FactoryBean。
FactoryBean接口
public interface FactoryBean<T> {
String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
@Nullable
T getObject() throws Exception;
@Nullable
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
代码示例
Car实体
public class Car {
private String color;
private String brand;
private double price;
// getters and setters...
}
CarFactoryBean
@Component("carFactoryBean")
public class CarFactoryBean implements FactoryBean<Car> {
@Override
public Car getObject() throws Exception {
System.out.println("FactoryBean的getObject替换掉getBean...");
return new Car();
}
@Override
public Class<?> getObjectType() {
return Car.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
测试类
public class Test01 {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
Car car = context.getBean(Car.class);
System.out.println(car);
}
}
// 打印结果
// FactoryBean的getObject替换掉getBean...
// com.example.Car@4d14b6c2
在实例化Bean过程比较复杂的情况下,如果按照传统的方式,则需要在中提供大量的配置信息。配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。Spring为此提供了一个 FactoryBean
的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。
FactoryBean 与 BeanFactory 的区别
-
BeanFactory是一个大工厂,是IOC容器的根基,有繁琐的bean声明周期处理过程,可以生成各种各样的Bean。
-
FactoryBean是一个小工厂,它自己本身也是一个Bean,但是可以生成其他Bean。用户可以通过实现该接口定制实例化Bean的逻辑。
这种设计模式本质上是一个工厂方法模式,通过公共的工厂接口和不同的具体工厂,来获取对象。