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/beanshttp://www.springframework.org/schema/beans/spring-beans-4.2.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.2.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc-4.2.xsdhttp://www.springframework.org/schema/taskhttp://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";@NullableT getObject() throws Exception;@NullableClass<?> 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> {@Overridepublic Car getObject() throws Exception {System.out.println("FactoryBean的getObject替換掉getBean...");return new Car();}@Overridepublic Class<?> getObjectType() {return Car.class;}@Overridepublic 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的邏輯。
這種設計模式本質上是一個工廠方法模式,通過公共的工廠接口和不同的具體工廠,來獲取對象。