1. Inferir o construtor antes da instanciação
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean
Criado um objeto BeanWrapper para relatar beans instanciados
iniciar instanciação
instanceWrapper = createBeanInstance(beanName, mbd, args);
acompanhamento
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance
Obtenha o tipo de classe do bean
Class<?> beanClass = resolveBeanClass(mbd, beanName);
Se o bean especificar um método de fábrica, ele entrará nele se o julgamento
底层会获取工厂方法【静态工厂方法|实例化方法】--> 然后解析方法入参 --> 然后执行反射调用创建实例 --> 封装为包装对象返回.
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
Se o bean for um protótipo, este branch será levado
Se não for um protótipo de bean, o método que inferiu o construtor será executado
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
O que está sendo instanciado agora é que o bean A não fornece explicitamente um construtor, um construtor sem argumento será fornecido por padrão, mas o spring não infere nenhum construtor
Em seguida, chame getPreferredConstructors para obter o construtor padrão
ctors = mbd.getPreferredConstructors();
Como resultado, ainda não recebo nada e finalmente chamo o método instantiateBean
// No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);
Condição para chegar aqui Nenhum método de retorno de chamada para criação de bean && Nenhum método de fábrica && Os parâmetros do construtor não são resolvidos && Nenhum construtor padrão pré-especificado
Acompanhe o método instantiateBean
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
Vamos primeiro ver qual é a estratégia de instanciação retornada
A estratégia de criação padrão é: CglibSubclassingInstantiationStrategy
2. Instancie beans
org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate
Obtenha o objeto de classe do bean, obtenha o construtor padrão, defina o construtor obtido como bd e, finalmente, chame BeanUtils.instantiateClass(constructorToUse) e passe o construtor
para org.springframework.beans.BeanUtils.instantiateClass
Ative a reflexão violenta no método BeanUtils.instantiateClass e, finalmente, o objeto construtor chama o método newInstance para concluir a instanciação
Pode-se ver que foi instanciado
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean方法
2.1 Chame o pós-processador MergedBeanDefinitionPostProcessor do bean
Chame o pós-processador do bean novamente, desta vez o bean foi instanciado, mas a injeção de propriedade não foi concluída
Chame o método postProcessMergedBeanDefinition de todos os MergedBeanDefinitionPostProcessors para processar os atributos marcados com anotações na classe e colocá-los no cache.
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
3. Depois que o Bean for instanciado, adicione-o ao cache L3
Continue a descer e veja mais três julgamentos consecutivos
Se o bean atual é um singleton, se as dependências circulares são permitidas, se ele está sendo criado, todos estão satisfeitos em continuar caindo
O parâmetro de chamada addSingletonFactory tem outra expressão lombad, que é muito usada
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
acompanhamento
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.addSingletonFactory
`Se não houver bean de instância única correspondente a beanName no pool de cache de instância única atual,
!this.singletonObjects.containsKey(beanName)
Coloque a expressão lombad no cache L3,
this.singletonFactories.put(beanName, singletonFactory);
E remova a instância do bean correspondente ao beanName do cache de segundo nível
this.earlySingletonObjects.remove(beanName);
`Salva o beanName atual na coleção Set correspondente ao bean registrado, indicando que ele foi registrado
this.registeredSingletons.add(beanName);
回到addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
Veja o que o método de substituição faz. Observe que ele não é chamado neste momento
Obtenha todos os pós-processadores para determinar se a interface SmartInstantiationAwareBeanPostProcessor está implementada e chame o getEarlyBeanReference de SmartInstantiationAwareBeanPostProcessor um por um. O Spring resolve o núcleo do problema de dependência circular de objetos proxy AOP
Em seguida, o método doCreateBean olha para baixo e chama populateBean(beanName, mbd, instanceWrapper) para entrar no estágio de preenchimento de atributo
4. Pós-processamento de InstantiationAwareBeanPostProcessor após a instanciação
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean
Chame o método InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() após a instanciação
Depois de ler a postagem anterior do blog, sei que InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation também é chamado antes da instanciação
Se substituirmos o método InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() e retornarmos false, a propriedade não será preenchida, o padrão será true
`Receba todas as propriedades do bean que está sendo instanciado no momento
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
O método de julgamento de preenchimento de propriedade @Autowired não pertence a ByName nem ByType
Se o bean atual tem um pós-processador do tipo InstantiationAwareBeanPostProcessor
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
Detecção de dependência
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
Se houver um pós-processador do tipo InstantiationAwareBeanPostProcessor, ele entrará na lógica de julgamento if e executará o método de pós-processador
5. Estágio de preenchimento de atributos
O método de preenchimento de propriedade real applyPropertyValues(beanName, mbd, bw, pvs);
applyPropertyValues(beanName, mbd, bw, pvs);
Acompanhamento em applyPropertyValues
Por fim, a propriedade é preenchida chamando o método setter por meio de reflexão
6. Execute três métodos de retorno de chamada cientes antes da inicialização
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean 方法
O método de inicialização é executado imediatamente após o preenchimento da propriedade
Em seguida, olhe para o método de inicialização
exposedObject = initializeBean(beanName, exposedObject, mbd);
acompanhamento
Chamou três métodos de retorno de chamada cientes BeanNameAware -> BeanClassLoaderAware -> BeanFactoryAware
Depois de executar os três métodos de retorno de chamada, chamar applyBeanPostProcessorsBeforeInitialization é outro pós-processador
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
7. Execute postProcessBeforeInitialization do BeanPostProcessor antes da inicialização
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization
Se o método postProcessBeforeInitialization retornar um objeto, o bean que está sendo inicializado será substituído. O bean que está sendo inicializado tem um valor de propriedade
Após executar o pré-método de inicialização do BeanPostProcessor, o método invokeInitMethods será executado e o método de inicialização será executado.
8. Execute o método de inicialização
invokeInitMethods(beanName, wrappedBean, mbd);
Primeiro, determine se a interface InitializingBean está implementada, se estiver implementada, o método afterPropertiesSet será executado.
Determine se há um método de inicialização especificado e, em caso afirmativo, execute o método de inicialização especificado por meio de reflexão
Depois que o método de inicialização for executado, volte para o método initializeBean, continue e execute o pós-método do BeanPostProcessor.
9. Execute postProcessAfterInitialization do BeanPostProcessor após a inicialização
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
O método BeanPostProcessor.postProcessAfterInitialization é incrível, a classe proxy é criada aqui e o AOP é baseado na implementação aqui
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean,
fora de initializeBean(beanName,posedObject, mbd)
Continue para baixo se houver uma dependência circular
Venha para o método getSingleton(beanName, false)
Preste atenção em getSingleton(beanName, false); ao chamar o parâmetro passado pelo método getSingleton, ele não irá para o cache de terceiro nível.
10. Adicione ao pool de buffers singleton
Depois que o bean for instanciado, volte para org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton e continue abaixo
O método afterSingletonCreation será chamado para remover o beanName da coleção beanName que está sendo criada
Em seguida, chame addSingleton(beanName, singletonObject); para adicionar o bean atual ao buffer pool singleton
`Coloque o bean de instância única criado no pool de cache singleton
this.singletonObjects.put(beanName, singletonObject);
`/ Remover do cache L3
this.singletonFactories.remove(beanName);
`Remover do cache L2
this.earlySingletonObjects.remove(beanName);
`Salvar na coleção de nomes de bean de instância única registrada
this.registeredSingletons.add(beanName);
Até agora, o ciclo de vida de um bean no Spring foi concluído e existem muitos processos.A próxima postagem do blog irá desenhar uma imagem em detalhes e explicar como o cache de terceiro nível resolve o problema da dependência circular.