BeanFactory
是 Spring 框架的核心接口,它提供了高级工厂模式的实现,能够管理和调配应用中的 beans。BeanFactory
以及它的子类(如 ApplicationContext
)负责实例化、配置和装配 beans。
以下是对 BeanFactory
接口和它的默认实现 DefaultListableBeanFactory
的一些关键源码解析。请注意,由于 Spring 源码非常复杂且包含大量的接口和类,这里仅提供部分关键片段的解析。
BeanFactory
接口定义了 Spring 容器的最基本行为,如获取 bean 实例:
public interface BeanFactory {
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
// 其他方法...
}
DefaultListableBeanFactory
是一个典型的 BeanFactory
实现,它包含了 bean 定义的注册以及依赖的处理。
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
// Bean定义映射,key是bean的名字,value是Bean定义
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
// 其他属性...
@Override
public <T> T getBean(Class<T> requiredType) throws BeansException {
return doGetBean(requiredType, null, null, false);
}
// doGetBean方法是获取Bean的核心方法,下面会做详细解析
protected <T> T doGetBean(final String name, final Class<T> requiredType,
final Object[] args, boolean typeCheckOnly) throws BeansException {
// 省略代码...
}
// 其他方法...
}
doGetBean
方法是实际获取 bean 实例的地方,它会进行很多检查和处理。
protected <T> T doGetBean(final String name, final Class<T> requiredType,
final Object[] args, boolean typeCheckOnly) throws BeansException {
// 提取对应的 beanName
String beanName = transformedBeanName(name);
Object bean;
// 尝试从缓存中加载单例
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
// 如果不是请求单例,则需要创建 bean
// 这里涉及到原型bean的创建,或者是在某些情况下单例bean的创建(比如使用了lazy-init的单例bean)
BeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 依赖处理
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
getBean(dep);
registerDependentBean(dep, beanName);
}
}
// 创建 bean 实例
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
// 销毁单例以避免悬挂资源
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
// 原型设计模式:每次请求都会创建一个新的实例
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
} finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else {
// 其他作用域的处理
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
} finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
} catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; " +
"consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
// 检查需要的类型是否符合bean的实际类型
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
} catch (TypeMismatchException e) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
在 doGetBean
方法中,Spring 容器首先会从缓存中查找对应的单例 bean,如果找到就使用,否则会根据 BeanDefinition 创建新的 bean 实例。创建过程包括了初始化前的依赖检查、依赖注入、初始化方法的调用以及可能的 AOP 代理相关处理。
此外,对于原型(prototype)作用域的 beans,每次调用 getBean
时都会创建一个新实例,而对于自定义作用域,将根据相应的作用域规则来决定 bean 的创建和生命周期管理。
上面的代码演示是一个非常精简的 BeanFactory
和 DefaultListableBeanFactory
的源码解析,实际上在 Spring 框架中,这些类包含更多的方法和更复杂的逻辑。
在使用 BeanFactory
时,你需要注意以下几点:
Spring 框架的源码是学习 Java 设计模式和高级框架架构的宝库,对于有志于深入理解 Spring 的开发人员来说,直接阅读和分析其源码是非常有价值的。