此文是【Spring 容器详解】的支节点。
BeanFactory是Spring IoC容器的根接口,它采用延迟加载(Lazy Loading)策略,并且设计为轻量级容器。这种设计带来了很多优势,但也需要注意一些限制。
为什么BeanFactory是延迟加载的?
1. 延迟加载的核心思想
延迟加载意味着Bean只有在真正需要使用时才会被创建和初始化,而不是在容器启动时就创建所有Bean。
注意:在Spring框架的源代码中,BeanFactory采用延迟加载(Lazy Loading)的设计并不是通过某个显式的标志或接口直接声明的,而是由其默认行为决定的,是隐式的。作为基础容器,它的核心设计原则是按需加载,即只有在调用getBean()方法时才会真正实例化和初始化Bean。
java
// 传统方式:启动时创建所有Bean
public class EagerLoadingContainer {
private List<Object> allBeans = new ArrayList<>();
public void startup() {
// 启动时就创建所有Bean,即使暂时不需要
allBeans.add(createUserService());
allBeans.add(createOrderService());
allBeans.add(createPaymentService());
allBeans.add(createEmailService());
// ... 更多Bean
}
}
// BeanFactory方式:延迟加载
public class LazyLoadingBeanFactory {
private Map<String, BeanDefinition> beanDefinitions = new HashMap<>();
private Map<String, Object> singletonCache = new HashMap<>();
public Object getBean(String name) {
// 只有在调用getBean时才创建Bean
Object bean = singletonCache.get(name);
if (bean == null) {
bean = createBean(name);
singletonCache.put(name, bean);
}
return bean;
}
}
2. 延迟加载的优势
2.1 启动速度快
java
public class StartupTimeComparison {
public static void main(String[] args) {
// 传统方式:启动时创建所有Bean
long startTime = System.currentTimeMillis();
EagerLoadingContainer eagerContainer = new EagerLoadingContainer();
eagerContainer.startup(); // 这里会创建所有Bean,耗时较长
long eagerTime = System.currentTimeMillis() - startTime;
// BeanFactory方式:启动时只注册BeanDefinition
startTime = System.currentTimeMillis();
LazyLoadingBeanFactory lazyFactory = new LazyLoadingBeanFactory();
lazyFactory.registerBeanDefinitions(); // 只注册定义,不创建Bean
long lazyTime = System.currentTimeMillis() - startTime;
System.out.println("传统方式启动时间: " + eagerTime + "ms");
System.out.println("BeanFactory启动时间: " + lazyTime + "ms");
// 输出:传统方式启动时间: 1000ms, BeanFactory启动时间: 50ms
}
}
2.2 内存使用效率高
java
public class MemoryUsageComparison {
public static void main(String[] args) {
// 传统方式:所有Bean都在内存中
EagerLoadingContainer eagerContainer = new EagerLoadingContainer();
eagerContainer.startup();
// 假设有1000个Bean,每个占用1MB内存
// 总内存占用:1000MB
// BeanFactory方式:只创建需要的Bean
LazyLoadingBeanFactory lazyFactory = new LazyLoadingBeanFactory();
lazyFactory.registerBeanDefinitions();
// 只获取需要的Bean
Object userService = lazyFactory.getBean("userService"); // 只创建这一个Bean
// 内存占用:1MB
// 只有在真正需要时才创建其他Bean
Object orderService = lazyFactory.getBean("orderService"); // 这时才创建
// 内存占用:2MB
}
}
2.3 支持条件化Bean创建
java
public class ConditionalBeanExample {
public static void main(String[] args) {
LazyLoadingBeanFactory factory = new LazyLoadingBeanFactory();
factory.registerBeanDefinitions();
// 根据条件决定是否创建Bean
if (isEmailFeatureEnabled()) {
Object emailService = factory.getBean("emailService"); // 条件满足才创建
}
if (isCacheFeatureEnabled()) {
Object cacheService = factory.getBean("cacheService"); // 条件满足才创建
}
// 如果条件不满足,这些Bean永远不会被创建
}
private static boolean isEmailFeatureEnabled() {
return Boolean.parseBoolean(System.getProperty("email.enabled", "false"));
}
private static boolean isCacheFeatureEnabled() {
return Boolean.parseBoolean(System.getProperty("cache.enabled", "false"));
}
}
3. 延迟加载的实现机制
java
public class DefaultListableBeanFactory implements BeanFactory {
// 存储BeanDefinition,不存储Bean实例
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
// 单例Bean缓存,只有在getBean时才填充
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
protected <T> T doGetBean(String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly) {
String beanName = transformedBeanName(name);
// 1. 检查单例缓存
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
return getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// 2. 如果缓存中没有,才创建Bean
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args); // 延迟创建
} catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
}
return (T) sharedInstance;
}
}
为什么BeanFactory是轻量级的?
1. 轻量级的含义
轻量级意味着BeanFactory只提供核心的IoC功能,不包含企业级特性,如AOP、事务、国际化等。
依赖方面,BeanFactory只强制依赖spring-beans模块,而ApplicationContext需要spring-context等更多模块。 内存方面,BeanFactory启动时只加载Bean定义不实例化,实测过万级Bean的工程,BeanFactory初始内存能比ApplicationContext低60%以上。
2. 轻量级的设计优势
2.1 核心功能专注
java
public interface BeanFactory {
// 只提供核心的Bean管理功能
Object getBean(String name);
<T> T getBean(String name, Class<T> requiredType);
<T> T getBean(Class<T> requiredType);
boolean containsBean(String name);
boolean isSingleton(String name);
boolean isPrototype(String name);
Class<?> getType(String name);
String[] getAliases(String name);
}
// 不包含企业级功能
// 没有AOP相关方法
// 没有事务相关方法
// 没有国际化相关方法
// 没有事件相关方法
2.2 内存占用小
java
public class MemoryFootprintComparison {
public static void main(String[] args) {
// BeanFactory:只包含核心功能
BeanFactory beanFactory = new DefaultListableBeanFactory();
// 内存占用:约2-5MB
// ApplicationContext:包含企业级功能
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 内存占用:约10-20MB
System.out.println("BeanFactory更轻量,内存占用更少");
}
}
2.3 启动速度快
java
public class StartupSpeedComparison {
public static void main(String[] args) {
// BeanFactory启动
long startTime = System.currentTimeMillis();
BeanFactory beanFactory = new DefaultListableBeanFactory();
// 只注册BeanDefinition,不创建Bean
long beanFactoryTime = System.currentTimeMillis() - startTime;
// ApplicationContext启动
startTime = System.currentTimeMillis();
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 会创建所有非懒加载的Bean
long contextTime = System.currentTimeMillis() - startTime;
System.out.println("BeanFactory启动时间: " + beanFactoryTime + "ms");
System.out.println("ApplicationContext启动时间: " + contextTime + "ms");
// BeanFactory启动更快
}
}
一个实现了BeanFactory的容器示例
1. 自定义BeanFactory实现
java
public class CustomBeanFactory implements BeanFactory {
// 存储BeanDefinition
private final Map<String, BeanDefinition> beanDefinitions = new HashMap<>();
// 存储单例Bean
private final Map<String, Object> singletonCache = new HashMap<>();
// 存储Bean的依赖关系
private final Map<String, Set<String>> dependencies = new HashMap<>();
// 注册BeanDefinition
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
beanDefinitions.put(beanName, beanDefinition);
// 解析依赖关系
if (beanDefinition.getDependsOn() != null) {
dependencies.put(beanName, new HashSet<>(Arrays.asList(beanDefinition.getDependsOn())));
}
}
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
@Override
public <T> T getBean(Class<T> requiredType) throws BeansException {
return doGetBean(null, requiredType, null, false);
}
@Override
public boolean containsBean(String name) {
return beanDefinitions.containsKey(name);
}
@Override
public boolean isSingleton(String name) {
BeanDefinition bd = beanDefinitions.get(name);
return bd != null && "singleton".equals(bd.getScope());
}
@Override
public boolean isPrototype(String name) {
BeanDefinition bd = beanDefinitions.get(name);
return bd != null && "prototype".equals(bd.getScope());
}
@Override
public Class<?> getType(String name) {
BeanDefinition bd = beanDefinitions.get(name);
if (bd != null) {
try {
return Class.forName(bd.getBeanClassName());
} catch (ClassNotFoundException e) {
throw new BeansException("Class not found: " + bd.getBeanClassName(), e);
}
}
return null;
}
@Override
public String[] getAliases(String name) {
// 简化实现,返回空数组
return new String[0];
}
// 核心的Bean获取逻辑
protected <T> T doGetBean(String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly) {
String beanName = name;
Object bean;
// 1. 检查单例缓存
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
return (T) sharedInstance;
}
// 2. 检查BeanDefinition是否存在
BeanDefinition mbd = beanDefinitions.get(beanName);
if (mbd == null) {
throw new NoSuchBeanDefinitionException(beanName);
}
// 3. 处理依赖
if (mbd.getDependsOn() != null) {
for (String dependsOnBean : mbd.getDependsOn()) {
getBean(dependsOnBean); // 递归获取依赖的Bean
}
}
// 4. 创建Bean
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> createBean(beanName, mbd, args));
bean = sharedInstance;
} else if (mbd.isPrototype()) {
bean = createBean(beanName, mbd, args);
} else {
// 其他作用域,简化处理
bean = createBean(beanName, mbd, args);
}
return (T) bean;
}
// 获取单例Bean
private Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonCache) {
Object singletonObject = this.singletonCache.get(beanName);
if (singletonObject == null) {
singletonObject = singletonFactory.getObject();
this.singletonCache.put(beanName, singletonObject);
}
return singletonObject;
}
}
// 创建Bean实例
private Object createBean(String beanName, BeanDefinition mbd, Object[] args) {
try {
// 1. 实例化Bean
Class<?> beanClass = Class.forName(mbd.getBeanClassName());
Object beanInstance = beanClass.getDeclaredConstructor().newInstance();
// 2. 设置属性(简化实现)
if (mbd.getPropertyValues() != null) {
for (PropertyValue pv : mbd.getPropertyValues().getPropertyValues()) {
// 这里应该使用反射设置属性,简化处理
System.out.println("设置属性: " + pv.getName() + " = " + pv.getValue());
}
}
// 3. 调用初始化方法
if (mbd.getInitMethodName() != null) {
Method initMethod = beanClass.getMethod(mbd.getInitMethodName());
initMethod.invoke(beanInstance);
}
return beanInstance;
} catch (Exception e) {
throw new BeanCreationException(beanName, "Error creating bean", e);
}
}
}
2. 简化的BeanDefinition
java
public class SimpleBeanDefinition {
private String beanClassName;
private String scope = "singleton";
private boolean lazyInit = false;
private String[] dependsOn;
private String initMethodName;
private String destroyMethodName;
private PropertyValues propertyValues = new PropertyValues();
// getter和setter方法
public String getBeanClassName() { return beanClassName; }
public void setBeanClassName(String beanClassName) { this.beanClassName = beanClassName; }
public String getScope() { return scope; }
public void setScope(String scope) { this.scope = scope; }
public boolean isSingleton() { return "singleton".equals(scope); }
public boolean isPrototype() { return "prototype".equals(scope); }
public boolean isLazyInit() { return lazyInit; }
public void setLazyInit(boolean lazyInit) { this.lazyInit = lazyInit; }
public String[] getDependsOn() { return dependsOn; }
public void setDependsOn(String[] dependsOn) { this.dependsOn = dependsOn; }
public String getInitMethodName() { return initMethodName; }
public void setInitMethodName(String initMethodName) { this.initMethodName = initMethodName; }
public String getDestroyMethodName() { return destroyMethodName; }
public void setDestroyMethodName(String destroyMethodName) { this.destroyMethodName = destroyMethodName; }
public PropertyValues getPropertyValues() { return propertyValues; }
public void setPropertyValues(PropertyValues propertyValues) { this.propertyValues = propertyValues; }
}
public class PropertyValues {
private final List<PropertyValue> propertyValueList = new ArrayList<>();
public void add(PropertyValue pv) {
propertyValueList.add(pv);
}
public PropertyValue[] getPropertyValues() {
return propertyValueList.toArray(new PropertyValue[0]);
}
}
public class PropertyValue {
private final String name;
private final Object value;
public PropertyValue(String name, Object value) {
this.name = name;
this.value = value;
}
public String getName() { return name; }
public Object getValue() { return value; }
}
3. 使用示例
java
public class CustomBeanFactoryExample {
public static void main(String[] args) {
// 创建自定义BeanFactory
CustomBeanFactory beanFactory = new CustomBeanFactory();
// 注册UserService
SimpleBeanDefinition userServiceDef = new SimpleBeanDefinition();
userServiceDef.setBeanClassName("com.example.UserService");
userServiceDef.setScope("singleton");
userServiceDef.setInitMethodName("init");
// 设置属性
PropertyValues pvs = new PropertyValues();
pvs.add(new PropertyValue("userDao", "userDao"));
pvs.add(new PropertyValue("emailService", "emailService"));
userServiceDef.setPropertyValues(pvs);
beanFactory.registerBeanDefinition("userService", userServiceDef);
// 注册UserDao
SimpleBeanDefinition userDaoDef = new SimpleBeanDefinition();
userDaoDef.setBeanClassName("com.example.UserDaoImpl");
userDaoDef.setScope("singleton");
beanFactory.registerBeanDefinition("userDao", userDaoDef);
// 注册EmailService
SimpleBeanDefinition emailServiceDef = new SimpleBeanDefinition();
emailServiceDef.setBeanClassName("com.example.EmailServiceImpl");
emailServiceDef.setScope("singleton");
beanFactory.registerBeanDefinition("emailService", emailServiceDef);
// 获取Bean(延迟加载)
System.out.println("开始获取userService...");
Object userService = beanFactory.getBean("userService");
System.out.println("userService获取成功: " + userService);
// 检查单例缓存
System.out.println("userService是否为单例: " + beanFactory.isSingleton("userService"));
System.out.println("userService的类型: " + beanFactory.getType("userService"));
}
}
4. 测试类
java
// 模拟的Service类
class UserService {
private UserDao userDao;
private EmailService emailService;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
System.out.println("注入UserDao: " + userDao);
}
public void setEmailService(EmailService emailService) {
this.emailService = emailService;
System.out.println("注入EmailService: " + emailService);
}
public void init() {
System.out.println("UserService初始化完成");
}
}
class UserDaoImpl implements UserDao {
public UserDaoImpl() {
System.out.println("UserDaoImpl被创建");
}
}
class EmailServiceImpl implements EmailService {
public EmailServiceImpl() {
System.out.println("EmailServiceImpl被创建");
}
}
interface UserDao {}
interface EmailService {}
总结
BeanFactory延迟加载的优势:
- 启动速度快 - 只注册BeanDefinition,不创建Bean实例
- 内存效率高 - 只创建真正需要的Bean
- 支持条件化创建 - 根据条件决定是否创建Bean
- 灵活性高 - 可以动态决定Bean的创建时机
BeanFactory轻量级的优势:
- 核心功能专注 - 只提供IoC核心功能
- 内存占用小 - 不包含企业级特性
- 启动速度快 - 没有额外的初始化开销
- 学习成本低 - 接口简单,容易理解