[Spring] Parte de análise do código-fonte do ciclo de vida do Bean Processo de preenchimento e inicialização de atributos

1. Inferir o construtor antes da instanciação

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean

imagem-20220403104229519

Criado um objeto BeanWrapper para relatar beans instanciados

iniciar instanciação

instanceWrapper = createBeanInstance(beanName, mbd, args);

imagem-20220403104722942

acompanhamento

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance

imagem-20220403104803001

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

imagem-20220403105138275

Se não for um protótipo de bean, o método que inferiu o construtor será executado

Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);

imagem-20220403105258260

imagem-20220403105344834

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

imagem-20220403105509464

Em seguida, chame getPreferredConstructors para obter o construtor padrão

ctors = mbd.getPreferredConstructors();

imagem-20220403105619176

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

imagem-20220403105913726

beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);

Vamos primeiro ver qual é a estratégia de instanciação retornada

imagem-20220403110042850

A estratégia de criação padrão é: CglibSubclassingInstantiationStrategy

2. Instancie beans

org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate

imagem-20220403110258931

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

imagem-20220403110623024

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

imagem-20220403110841317

Pode-se ver que foi instanciado

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean方法

imagem-20220403111419852

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);

imagem-20220403111643781

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

imagem-20220403112121449

O parâmetro de chamada addSingletonFactory tem outra expressão lombad, que é muito usada

addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

imagem-20220403112256280

acompanhamento

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.addSingletonFactory

imagem-20220403112433721

`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

imagem-20220403113143498

Em seguida, o método doCreateBean olha para baixo e chama populateBean(beanName, mbd, instanceWrapper) para entrar no estágio de preenchimento de atributo

imagem-20220403113642811

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

imagem-20220403113857627

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

imagem-20220403120849770

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

imagem-20220403121147250

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);

imagem-20220403121420005

Acompanhamento em applyPropertyValues

imagem-20220403121534423

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 方法

imagem-20220403122213607

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);

imagem-20220403122307427

acompanhamento

imagem-20220403122323649

Chamou três métodos de retorno de chamada cientes BeanNameAware -> BeanClassLoaderAware -> BeanFactoryAware

imagem-20220403122631719

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

imagem-20220403122821818

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);

imagem-20220403123223622

Primeiro, determine se a interface InitializingBean está implementada, se estiver implementada, o método afterPropertiesSet será executado.

imagem-20220403123324702

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

imagem-20220403123421602

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.imagem-20220403123618646

9. Execute postProcessAfterInitialization do BeanPostProcessor após a inicialização

applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

imagem-20220403123737843

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)

imagem-20220403124304428

Continue para baixo se houver uma dependência circular

Venha para o método getSingleton(beanName, false)

imagem-20220403124337224

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

imagem-20220403125446954

O método afterSingletonCreation será chamado para remover o beanName da coleção beanName que está sendo criada

imagem-20220403125722699

imagem-20220403125630910

Em seguida, chame addSingleton(beanName, singletonObject); para adicionar o bean atual ao buffer pool singleton

imagem-20220403125754389

`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.

Acho que você gosta

Origin blog.csdn.net/JAVAlife2021/article/details/123935985
Recomendado
Clasificación