предисловие
В предыдущей статье мы представили процесс инициализации контейнера Spring IoC —Инициализация контейнера IoC
В этой статье мы продолжаем знакомить вас с интерпретацией процесса и исходного кода внедрения зависимостей Spring IoC.
Как и прежде, я разберу шаги для всех, чтобы у всех был общий контекст в душе, легче было читать исходный код и легче улавливать ключевые моменты.
основное содержание:
- преобразование разрешения beanName
- Регистрация Bean Detection вручную
- Обнаружение родительского контейнера
- Инициализация зависимости (рекурсивная)
- ★ Создайте одноэлементный экземпляр
- создание экземпляра объекта
- сбор имущества
- Обработка различных событий обратного вызова после создания bean-компонента
- ...
Анализ исходного кода
Последний раздел предыдущей главы, предпоследний шаг инициализации контейнера,finishBeanFactoryInitialization(beanFactory)
Создайте экземпляр всех синглетонов, вызовитеgetBean()
метод создания экземпляра одноэлементного компонента. Это точка входа для внедрения зависимостей Spring IoC.
Прежде чем мы начнем, необходимо упомянуть одну вещь. Раньше мы заходили после инициализации контейнера, но в реальной работе мы можем использоватьApplicationContext.getBean()
чтобы получить боб в контейнере. Не ограничивайте себя только точкой зрения.
Теперь давайте начнем.
Первый взглядgetBean()
Местоположение источника:AbstractBeanFactory#getBean(String name)
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
doGetBean()
deGetBean()
- преобразование разрешения beanName
- Обнаружение Зарегистрировать bean-компоненты вручную
- Обнаружение родительского контейнера
- Инициализация зависимости (рекурсивная)
- Создать бин
createBean()
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 反正就是获取到真正beanName
// 处理两个情况,1. 将别名转化成真的beanName;2. 把FactoryBean的前缀"&"给去了
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
// 检测已经注册的Bean,保证不重复创建
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 这个方法还是有点逻辑的
// 如果目前获得的sharedInstance 不是FactoryBean,那bean就赋值成sharedInstance,直接返回
// 如果是FactoryBean就返回FactoryBean创建的实例,
// 这个也是FactoryBean的知识点,我在我的另一篇文章也讲过了,
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// 直接翻译:创建过了此 beanName 的 prototype 类型的 bean,那么抛异常
// We're assumably within a circular reference.
// 往往是因为陷入了循环引用
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
// 检查下这个BeanDefinition是否存在
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
// 当前容器没有这个BeanDefinition,去parent 容器去找
String nameToLookup = originalBeanName(name);
if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
// 这个 getMergedLocalBeanDefinition 前面讲过哦
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 先初始化依赖的所有 Bean,这个很好理解。
// 注意,这里的依赖指的是 depends-on 中定义的依赖
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
// 这里循环依赖概念不要紊乱了
// 这里指的是通过 depends-on 定义造成的循环依赖,
// 我们另外一种类成员式的循环引用Spring是支持的
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 注册依赖关系
// 这么做的原因是Spring在即将进行bean销毁的时候会【首先销毁被依赖的bean】。
// 看SpringBean的初始化和销毁顺序就知道了,依赖关系的保存目的就是这个
// 依赖关系的保存是通过一个ConcurrentHashMap<String, Set>完成的,key是bean的真实名字。
registerDependentBean(dep, beanName);
try {
// 先去初始化被依赖项
// 递归然后反递归回来
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
// 如果是 singleton scope 的,创建 singleton 的实例
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
// 创建Bean的详情,等下拉出来单独说
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
// 前面讲过了
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 如果是 prototype scope 的,创建 prototype 的实例
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
// 如果不是 singleton 和 prototype 的话,需要委托给相应的实现类来处理
// 这里非重点,我们的重点是singleton的创建
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, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
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);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// Check if required type matches the type of the actual bean instance.
// 最后再检查下类型对不对,不对就抛异常了,对的话就返回
if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
doCreateBean()
Обзор шагов:
- Если это синглтон в начале, сначала очистите кеш;
- Создать экземпляр bean-компонента, преобразовать BeanDefinition в BeanWrapper;
- Используя MergedBeanDefinitionPostProcessor, аннотация Autowired предназначена для достижения предварительного разрешения типа с помощью этого метода;
- Решить проблему циклической зависимости;
- Заполните свойства, заполните свойства в экземпляре компонента;
- Зарегистрируйте DisposableBean;
- Создано и возвращено
Три заботы:
- Создание экземпляра createBeanInstance()
- populateBean(); сборка свойств
- initializeBean() обрабатывает различные события обратного вызова после инициализации Bean.
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
// Instantiate the bean.
// 这个BeanWrapper是创建出来持有对象的
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
// 如果是singleton,先把缓存中的同名bean消除
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null)
// 关键代码,后面拉出来单独讲
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
// Allow post-processors to modify the merged bean definition.
// 涉及接口:MergedBeanDefinitionPostProcessor
// 不是关键逻辑,不讲了
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 这里是为了解决循环依赖的,先把初步实例化的Bean实例的引用缓存起来,暴露出去,
// 这个可以结合别的文章学习,面试题常考,我后面可能也会写
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 时序图中的一步,关键步骤,属性装配,前面的实例只是实例化,没有装配属性
// 和前面的createBeanInstance一样会拉出来讲,继续看下去吧
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 还记得 init-method 吗?还有 InitializingBean 接口?还有 BeanPostProcessor 接口?
// 这里就是处理 bean 初始化完成后的各种回调
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
// 这个逻辑分支我一次性说完吧。
// 如果该beanName对象已经注册单例模式,则从单例中获取,并判断获取到的bean实例(B)与BeanWrapper中的bean实例(A)是同一个实例,如果是,则返回A或者B,如果不是,则递归找出它的依赖bean。
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
// earlySingletonReference只有在检测到有循环依赖的情况下才会不为空
if (earlySingletonReference != null) {
if (exposedObject == bean) {
// 两个是同一个引用,bean初始化完成
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
// 注册DisposableBean;
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
Три проблемных момента на предыдущем шаге обсуждаются отдельно.
1. createBeanInstance()
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
// Make sure bean class is actually resolved at this point.
// 解析出 Class
Class<?> beanClass = resolveBeanClass(mbd, beanName);
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
// 如果工厂方法不为空,则是用工厂方法初始化
if (mbd.getFactoryMethodName() != null) {
// 相关知识点看另一篇文章关于FactoryBean的
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
// 如果不是第一次创建,比如第二次创建 prototype bean。
// 这种情况下,我们可以从第一次创建知道,采用无参构造函数,还是构造函数依赖注入 来完成实例化
// 所以注释说叫shortcut
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
// 有已经解析过的构造方法
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
// 如果已经解析过则使用解析好的构造方法不需要再次锁定
if (resolved) {
if (autowireNecessary) {
// 构造方法自动注入
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 默认构造方法
return instantiateBean(beanName, mbd);
}
}
// Need to determine the constructor...
// 判断是否采用有参构造函数
// 构造器自动装配
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// No special handling: simply use no-arg constructor.
// 使用无参构造器
return instantiateBean(beanName, mbd);
}
2. populateBean(); сборка свойств
Способ входа:AbstractAutowireCapableBeanFactory#populateBean
,
Его роль: по типу автопроводкиautowire by name
,by type
Или установить его напрямую
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
if (bw == null) {
if (!pvs.isEmpty()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
// 这里看注解是一个扩展点
// InstantiationAwareBeanPostProcessor 的实现类可以在这里对 bean 进行状态修改
// 不是个常用的扩展点,这里不讲了
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 如果返回 false,代表不需要进行后续的属性设值,也不需要再经过其他的 BeanPostProcessor 的处理
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
if (!continueWithPropertyPopulation) {
return;
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
// 通过名字找到所有属性值,如果是 bean 依赖,先初始化依赖的 bean。记录依赖关系
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
// 通过类型装配
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
// InstantiationAwareBeanPostProcessor.postProcessPropertyValues方法
// 代表能对属性值进行修改的能力
// 其中一个很有用实现类提一下,AutowiredAnnotationBeanPostProcessor
// 对采用@Autowired和@Value设值的就是这个BeanPostProcessor干的。
// 不展开讲了,不然要讲不完了
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
// 这里才是设置bean实例的属性值
applyPropertyValues(beanName, mbd, bw, pvs);
}
3. InitializeBean() обрабатывает различные события обратного вызова после инициализации Bean.
См. описание этого метода в javadoc.
Initialize the given bean instance, applying factory callbacks as well as init methods and bean post processors.
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
// 涉及到的回调接口点进去一目了然,代码都是自解释的
// BeanNameAware、BeanClassLoaderAware或BeanFactoryAware
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// BeanPostProcessor 的 postProcessBeforeInitialization 回调
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// init-methods
// 或者是实现了InitializingBean接口,会调用afterPropertiesSet() 方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// BeanPostProcessor 的 postProcessAfterInitialization 回调
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
Мы обнаружили, что нет, здесь происходят два обратных вызова BeanPostProcessor, но init-метод обрабатывается посередине. Это немного отличается от моего первоначального восприятия? Поскольку наименование кода в исходном коде Spring часто говорит само за себя, много раз я знал назначение этих методов, читая по-английски, но здесь, почему метод предварительной обработки BeanPostProcessorpostProcessBeforeInitialization()
Также вызывается после завершения настройки свойства?
После запроса, чтобы увидеть объяснение на английском языке,
BeanPostProcessor is used to interact with newly created bean instances before and/or after their initialization method is invoked by the Spring container. You can use BeanPostProcessor to execute custom logic before and/or afterМетод инициализации бина вызывается контейнером Spring.
Целью BeanPostProcessor является выполнение пользовательских операций до и после метода инициализации. Если подумать, то кажется, что в названии нет ничего плохого. Если он действительно вызывается до создания экземпляра SpringBean, его следует вызыватьBeforeInstantiation
. в исходном кодеinitialization
означает вышеуказанноеinvokeInitMethods
работать.
Эпилог
Вышеизложенное является основным содержанием внедрения зависимостей Spring IoC.
Контейнер Spring IoC. Здесь есть и другие сведения о функциях Spring IoC. Например, жизненный цикл компонента Spring, FactoryBean, BeanPostProcessor — все это функции, которые часто встречаются при использовании контейнера Spring IoC. После понимания общего принципа работы контейнера IoC вы сможете выполнить некоторый анализ этих функций и объединить свои методы использования этих функций с исходным кодом, чтобы вы могли полностью их понять.
На данный момент "грубая" интерпретация Spring IoC исходного кода внедрения зависимостей завершена. Тем не менее, приведенный выше анализ исходного кода определенно не будет полным, а будет извлекать только то, что я считаю важным.
Если есть какие-либо упущения, пожалуйста, поймите и проверьте соответствующую информацию самостоятельно. Если не так, поправьте меня!
Эта статья опубликована в блогеOpenWriteвыпуск!