The BeanFactory system
BeanFactory
The top-level interface of the bean container, which defines the basic functionality provided by the container.
- GetBean (String beanName)– > Get the bean by name
- GetBean (Class classType)– > Get the bean by type
- IsSingleton (String beanName)– > Whether it is a singleton
- IsPrototype (String beanName)– > Whether it is a prototype
- .
Note: Only the ability to get a single bean instance is provided here
The BeanFactory immediate child interface: HierarchicalBeanFactory ListableBeanFactory, AutowireCapableBeanFactory
HierarchicalBeanFactory
For factories with hierarchical capabilities, the main addition is the getParentBeanFactory() method, so called parent-child containersCopy the code
ListableBeanFactory
String [] getBeanNamesForType(Class<T> classType)-- > getBeanNamesForType(Class<T> classType)-- > getBeanNamesForType(Class<T> classType)-- > getBeanNamesForType(Class<T> classType)-- > getBeanNamesForType(Class<T> classType)-- > getBeanNamesForType Map<String,T> getBeanOfType(Class<T> classType)-- > getBeanOfType(Class<T> classType)-- > Get a collection of bean instances of the specified type in the bean container... Isocorrelation methodCopy the code
AutowireCapableBeanFactory
Equip factories, add autowireBean(),createBean(Class<T> classType)... Isocorrelation methodCopy the code
While marveling at the complexity of Spring’s various inheritance systems, it is really hard to blog for the first time, so I will not continue with the introduction (mainly because I haven’t fully experienced it yet), so I will simply learn the source code
IOC source code analysis
Pre-knowledge: mainly for the purpose of sweeping a blind, have understood can directly skip
What are the key steps involved in creating a normal, complete singleton bean in the Spring container?
1.1 Instantiation
~Supplier interface normally, we do not use it ourselves. It is used within the framework. I caught a glimpse of it while looking at Mybatis source code. Static factory method and factory instance method @bean annotation will go here. Parameter construction ~ no-parameter construction mainly creates Bean instances by calling the default constructor through reflection. In this case, the Bean properties are still null or the initial value of the primitive data type. Calls to the argument constructor that perform the corresponding fill logic (if any) are another matterCopy the code
1.2 Attribute Population
Inject properties, called DI(dependency injection), @value @AutoWired @resource, etcCopy the code
1.3 Initialization
Execute the specified initialization method to complete the customized initialization. The following operations are performed in sequence: InvokeAwareMethods postProcessBeforeInitialization, @ PreConstruct annotations treated afterPropertiesSet here, The current Bean implementation InitializingBean interface when the init method, postProcessAfterInitialization AOP to create one of the entrance to the proxy object Note: @ PreConstruct will be CommonAnnotationBeanPostProcessor - > InitDestroyAnnotationBeanPostProcessor# postProcessBeforeInitialization method processing
Copy the code
What is level 3 caching in Spring?
2.1 Map
singletonObjects = new ConcurrentHashMap<>(256)– > Level-1 cache
It holds instances of singleton beans that have completed the instantiation, property population, and initialization steps
2.2 Map
earlySingletonObjects = new HashMap<>(16)– > Secondary cache
It holds a pre-exposed singleton bean instance, which may bea proxy object or an unpropped original object, but has not completed the initialization step
2.3 the Map < String, the ObjectFactory
> singletonFactories = new HashMap<>(16)–
It holds an anonymous inner class instance of ObjectFactory, a callback to getEarlyBeanReference() that gets a reference to a pre-exposed singleton bean, highlighted here because it is where proxy object creation, or AOP aspect weaving, can take place.
Note of caution: This is only an analysis of the complete process of creating a singleton bean for the first time, not considering that the bean is already in the container-level cache (the bean is fully created)
Entry: AbstractBeanFactory# getBean
This abstract class implements getBean(String beanName), Final String Name,@Nullable Final Class requiredType,@Nullable Final Object[] args, Boolean typeCheckOnly), the main process of this method is as follows:
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory { protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { Object bean; Final String beanName transformedBeanName(name) 2.Object sharedInstance = DefaultSingletonBeanRegistry#getSingleton(beanName); if sharedInstance ! Bean = getObjectForBeanInstance(sharedInstance, name, beanName) Null) 3. IsPrototypeCurrentlyInCreation (beanName) / / if the prototype bean circular dependencies directly thrown exception 4. The BeanFactory parentBeanFactory = getParentBeanFactory(); if parentBeanFactory ! = null && ! Abstractbeandefinition (beanName) {// AbstractBeanDefinition (beanName) {// AbstractBeanDefinition (beanName) {// AbstractBeanDefinition is not empty. 5. MarkBeanAsCreated (beanName); / / marks come to alreadyCreated beanName 6. The final RootBeanDefinition MBD = getMergedLocalBeanDefinition (beanName); 7.checkMergedBeanDefinition(mbd, beanName, args); 8.String[] mbd.getDependson (); if dependsOn ! > < div style = "color: RGB (51, 51, 51); 9. If (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, () -> {try {return createBean(beanName, MBD, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; }}); 10.bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } 11.T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType) if convertedBean ! = null // not null return convertedBean; 12. return <T> bean } }Copy the code
Non-important steps have been annotated in the pseudo-code, and other important steps are explained as follows:
- <1> Getting the raw bean name There are two main things done here
- Remove the prefix “&” from name
- Getting the bean’s original name from aliasMap resolves the aliasA– >aliasB– >ABean multiple alias case
- <2> Attempts to fetch bean instances from level 1 cache, linked here to
DefaultSingletonBeanRegistry#getSingleton(beanName)
- <4> when the parent container is not empty and there is no beanName bean definition information in the current container, try to get the bean from the parent container, another call process of AbstractBeanFactory#getBean is ignored here
- <6> Merge BeanDefinition information from parent class, main processing method overwrite, etc., which has not been thoroughly understood here
- <9> Create the bean instance, linked here to
DefaultSingletonBeanRegistry#getSingleton(beanName,objectFactory)
Method that passes an anonymous inner class instance of the ObjectFactory, triggered by the getObject() method callbackAbstractAutowireCapableBeanFactory#createBean(String beanName, RootBeanDefinition mbd, Object[] args)
The implementation of the - < > 10 judgment
createBean()
Return instance sharedInstance- sharedInstance instanceOf FactoryBean
- The name containing the & prefix directly returns the FactoryBean object sharedInstance
- The name does not contain the & prefix. Calling the sharedinstance.getobject () method returns the real bean
- ! SharedInstance instanceOf FactoryBean returns sharedInstance directly
- sharedInstance instanceOf FactoryBean
- <11,12> do the necessary type conversions
DefaultSingletonBeanRegistry#getSingleton
The three overloaded methods of getSingleton are described here in the order in which they are called
Raw interface methodgetSingleton(String beanName)
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
// The original interface method
@Override
@Nullable
public Object getSingleton(String beanName) {
return getSingleton(beanName, true); }}Copy the code
A method that implements the SingletonBeanRegistry interface, internally calling overloaded method 1 with allowEarlyReference parameter true, which is called earlier at the start of AbstractBeanFactory#doCreateBean
Overload method 1getSingleton(String beanName, boolean allowEarlyReference)
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
// Override method 1
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Get the singleton from the level 1 cache
Object singletonObject = this.singletonObjects.get(beanName);
/ / isSingletonCurrentlyInCreation: whether the current beanName in singletonsCurrentlyInCreation collection
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// Try to get the pre-exposed singleton bean reference from the secondary cache. The getEarlyBeanReference will only exist if it is pre-called
singletonObject = this.earlySingletonObjects.get(beanName);
// allowEarlyReference allows ObjectFactory#getObject to be retrieved from level 3 cache
if (singletonObject == null && allowEarlyReference) {
// Fetch from level 3 cacheObjectFactory<? > singletonFactory =this.singletonFactories.get(beanName);
if(singletonFactory ! =null) {
/ / callback ObjectFactory# getObject method for exposing reference in advance, which triggered AbstractAutowireCapableBeanFactory# getEarlyBeanReference execution
singletonObject = singletonFactory.getObject();
// Move from level 3 cache to level 2 cache
this.earlySingletonObjects.put(beanName, singletonObject);
// Remove the level 3 cache
this.singletonFactories.remove(beanName); }}}}returnsingletonObject; }}Copy the code
The overloaded method is mainly called in two places, and the allowEarlyReference passed in the two calls is different, so the two calls represent different meanings
-
First call: call chain (only the key method execution chain is listed), passing the allowEarlyReference to true
AbstractBeanFactory --->#getBean --->#doGetBean --->DefaultSingletonBeanRegistry#getSingleton(beanName) --->#getSingleton(beanName,true) Copy the code
There are two cases of cyclic dependency that are analyzed here
-
There is no circular dependencies: the situation is simpler, because in the early time this method is called at the beginning, specify beanName did not appear in the singletonsCurrentlyInCreation collection, so if level cache does not exist when the return null directly
-
There are circular dependencies: suppose A – > B, B – > A, and to create A pay attention to both the constructor dependence, spring is unable to solve this kind of circular dependencies, complains, because in the l3 cache is the premise of Bean instantiation, and the key to the solution of the circular dependencies are three levels of cache, of course, the second level cache is the cause of its existence.
The first call to getBean(A) creates A, and then enters the method
BeanName A/B returns null the first time it enters the method
To beanName 2. A/B instantiation, instantiation at singletonsCurrentlyInCreation beanName A/B will be placed before the collection
2.1 If beanName A/B is not A constructor dependent on beanName B/A, there is A key operation that exposes the instantiated bean in advance after A/B completes the instantiation operation. By creating a new anonymous inner class instance of the ObjectFactory interface (whose getObject callback method triggers the execution of the getEarlyBeanReference, returning the pre-exposed bean, and where Aop can be enhanced), Then, when we populate the properties, we find A dependency on B/A
2.2 If A/B constructor is dependent on B/A, it will be found to be dependent on B/A when A/B is instantiated. Note that there is no pre-exposed bean A/B in the tertiary cache at this time, so in this case, it must force B/A to call getBean(beanName) method before A/B, otherwise there will still be A problem. Spring will adjust the order of Bean creation in anticipation of this situation
Call getBean(B) a second time to create B and repeat the above steps
3. So here, A and B, respectively, the above steps, the third time when call getBean (A) create A, or B fill A, because A and B were performed the above steps, so A, B have existed singletonsCurrentlyInCreation collection, Instead of returning directly in step 1, the anonymous inner class instance of the ObjectFactory interface is retrieved from the level 3 cache and getObject() is called to trigger getEarlyBeanReference, which returns the previously exposed bean reference and then places the reference into the level 2 cache. Remove the corresponding level 3 cache.
4. Therefore, B successfully completes the attribute filling and initialization work, and finally A successfully obtains the dependency from B, completes the subsequent initialization work, and perfectly solves the problem of cyclic dependency.
-
Second call: the call chain is (only the key method execution chain is listed), and the allowEarlyReference is passed in as false
AbstractBeanFactory --->getBean --->doGetBean --->DefaultSingletonBeanRegistry --->getSingleton(beanName) --->getSingleton(beanName,true) --->getSingleton(beanName,objectFactory) --->objectFactory.getObject() --->AbstractAutowireCapableBeanFactory --->createBean --->doCreateBean --->createBeanInstance --->populateBean --->initializeBean --->getSingleton(beanName,false) Copy the code
That is, after the bean has been instantiated, populated with properties, and initialized. If the specified beanName has a circular dependency, and the getEarlyBeanReference is executed to move the previously exposed bean from level 3 to Level 2, then the bean returned here is not empty, and the effect of this is analyzed later.
Overloaded method 2getSingleton(String beanName, ObjectFactory<? > singletonFactory)
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
// Override method 2
public Object getSingleton(String beanName, ObjectFactory
singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
/ /... omit
/ / put the current beanName singletonsCurrentlyInCreation collection
beforeSingletonCreation(beanName);
boolean newSingleton = false;
/ /... omit
try {
/ / call the anonymous inner class for singletons, trigger AbstractAutowireCapableBeanFactory# createBean method of execution, createBean method will perform complete instantiation, fill, initialization work
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
/ /... omit
}
catch (BeanCreationException ex) {
/ /... omit
}
finally {
/ / the current beanName removed from singletonsCurrentlyInCreation collection
afterSingletonCreation(beanName);
}
// Put the generated singleton Bean into the level 1 cache, and remove the level 2 and level 3 caches
if(newSingleton) { addSingleton(beanName, singletonObject); }}returnsingletonObject; }}}Copy the code
GetSingleton (String beanName) is called when null is returned on the first call to the original interface method, passing in an anonymous inner class instance of the ObjectFactory interface. This method does four things:
-
Put the current beanName singletonsCurrentlyInCreation collection
-
To invoke an anonymous inner class instance object’s getObject () method to trigger the AbstractAutowireCapableBeanFactory# createBean method of execution, createBean method will perform complete instantiation, fill, initialization work
-
Removed from the current beanName singletonsCurrentlyInCreation collection
-
The generated singleton Bean is placed in the level 1 cache, and the level 2 and level 3 caches are removed
AbstractAutowireCapableBeanFactory#createBean
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
RootBeanDefinition mbdToUse = mbd;
1.Class<? > resolvedClass = resolveBeanClass(mbd, beanName);2.mbdToUse.prepareMethodOverrides();
// One of the entry points to create proxy objects, but the conditions here are more stringent, the normal bean creation process will not go through this point
3.Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if(bean ! =null) {
return bean;
}
// Complete Bean instance creation (instantiate, populate properties, initialize)
4.Object beanInstance = doCreateBean(beanName, mbdToUse, args);
returnbeanInstance; }}Copy the code
AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
// Another special entry to AOP for texturing requires that an instance of beanName has already been created in the beanFactory and that a custom TargetSourceCreator interface implementation class exists
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if(! Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {// Make sure bean class is actually resolved at this point.
if(! mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { Class<? > targetType = determineTargetType(beanName, mbd);if(targetType ! =null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if(bean ! =null) { bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } mbd.beforeInstantiationResolved = (bean ! =null);
}
returnbean; }}Copy the code
AbstractAutowireCapableBeanFactory#doCreateBean
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
/** * where the Bean is actually created *@param beanName
* @param mbd
* @param args
* @return
* @throws BeanCreationException
*/
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
Step 1: Instantiate the bean with no arguments by default
// Construct parameter dependency injection, which occurs in this step
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// Instantiated Bean object
finalObject bean = instanceWrapper.getWrappedInstance(); Class<? > beanType = instanceWrapper.getWrappedClass();if(beanType ! = NullBean.class) { mbd.resolvedTargetType = beanType; }// ...
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// Key steps to resolve loop dependencies
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
// If the singleton Bean needs to be exposed ahead of time, putting the Bean into the level 3 cache defaults to true
if (earlySingletonExposure) {
// ...
SingleFactories (key beanName, value ObjectFactory)
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// Bean creation Step 2: Populate properties (DI dependency injection occurs in this step)
populateBean(beanName, mbd, instanceWrapper);
Step 3: Call the initialization method to complete the bean initialization (AOP's third entry)
// Of AOP is through automatic proxy creator AbstractAutoProxyCreator postProcessAfterInitialization () method of execution for proxy objects created, AbstractAutoProxyCreator BeanPostP Implementation of rocessor interface
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
// ...
}
// There is an important point here that I missed when I first looked at it
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
// If the earlySingletonReference obtained from the secondary cache after being processed by getEarlyBeanReference() is not empty, the earlySingletonReference may be a proxy object or an original object
if(earlySingletonReference ! =null) {
// If the bean after initialization is equal to the previously exposed bean
/ / because at initialization time post processor postProcessAfterInitialization () method processing can create a proxy object, or may not create a proxy object, not to create a proxy object there are two reasons, 1. The bean itself need not be agents, 2. Already proxied in earlySingletonReference and added to earlyProxyReferences, the proxy is skipped and the original object is returned
/ / here are equal, if not create in explain postProcessAfterInitialization agent
if (exposedObject == bean) {
// Assign the earlySingletonReference to exposedObject, whether the post-handler was initialized because the agent was skipped or no agent was needed
// The earlySingletonReference is itself a proxy object when the proxy is skipped
/ / don't need agent in itself The three earlySingletonReference exposedObject, beans are the original object, does not affect
/ / so the key point here is to avoid postProcessAfterInitialization () will return to the original object caused by the skip agent, so this is the second level cache, the significance of early place agent may object to the second level cache
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
/ / allowRawInjectionDespiteWrapping default to false, then if have already rely on the current object, For example, cyclic dependencies get the current object in advance from getEarlyBeanReference() for dependency injection, because exposedObject! = bean postProcessAfterInitialization () returns the proxy objects
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
// If the object B that depends on the current object A finds that the object A depends on is the original object, this error can be reported when the object A @Async annotation has A cyclic dependency and is used incorrectly. Because the proxy object is created by postProcessAfterInitialization (), in getEarlyBeanReference () is not to create a proxy object
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."); }}}}// ...
returnexposedObject; }}Copy the code
AbstractAutowireCapableBeanFactory#getEarlyBeanReference
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if(! mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
// The second entry for AOP to create proxy objects is created by AbstractautoXyCreator by defaultexposedObject = ibp.getEarlyBeanReference(exposedObject, beanName); }}}returnexposedObject; }}Copy the code
AOP creates three entrances to proxy objects
Here is a direct transition to the AOP part of the source code, peep at the AOP proxy to create the entry method, in order, on a glance ha ha, more than the top
AbstractAutoProxyCreator#postProcessBeforeInstantiation
Earlier this method is called, in AbstractAutowireCapableBeanFactory# createBean method called, but in AbstractAutowireCapableBeanFactory# doCreateBean method before, That is, the call before instantiation
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor.BeanFactoryAware {
@Override
public Object postProcessBeforeInstantiation(Class
beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName);
/ / have been informed or have been customTargetSourceCreators create outdated directly returns null
if(! StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
/ / is infrastructure interface Advice. Class, Pointcut. Class, Advisor, AopInfrastructureBean. Word class or a class should be jumped out directly returns null
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null; }}// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
/ * * * here requires the beanFactory is not empty, custom customTargetSourceCreators (i.e., custom TargetSourceCreator implementation class) is not empty, And the beanFactory already has the bean *, so the normal bean creation will not create the proxy object */ here
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if(targetSource ! =null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
// Get interceptors and sink to the concrete subclass implementation
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
// Create a proxy object
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null; }}Copy the code
AbstractAutoProxyCreator#getEarlyBeanReference
The method is general in the case of a circular dependencies other objects, by relying on the current object invocation, by DefaultSingletonBeanRegistry# getSingleton (beanName, true) call triggered, ObjectFactory, a callback instance of a pre-exposed reference, is obtained from the level 3 cache and triggered by calling the objectFactory#getObject().
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor.BeanFactoryAware {
@Override
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
// Start by getting beanName, which basically prefixes the FactoryBean type with &
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// Check whether the references collection is already in earlyProxyReferences or not
if (!this.earlyProxyReferences.contains(cacheKey)) {
this.earlyProxyReferences.add(cacheKey);
}
// Create proxy objects, if necessary
return wrapIfNecessary(bean, beanName, cacheKey);
}
/**
* Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
* @param bean the raw bean instance
* @param beanName the name of the bean
* @param cacheKey the cache key for metadata access
* @return a proxy wrapping the bean, or the raw bean instance as-is
*/
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// Make some basic judgments first
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
/ / Advice/Pointcut/Advisor/AopInfrastructureBean interface beanClass is not acting as well as within the beanName for aop on aspects of agent
// See the subclass override shouldSkip() method here
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
// Find the collection of Advisor objects associated with the proxy class, where the point-cut expression is concerned
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// Take the proxy only when the corresponding advisor is not empty
if(specificInterceptors ! = DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE);
// Using JDK dynamic proxy or Cglib dynamic proxy, the proxy object is passed in as SingletonTargetSource object, wrapping the original bean object
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
// Put the proxy type cache
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
// Put into the notification cache
this.advisedBeans.put(cacheKey, Boolean.FALSE);
returnbean; }}Copy the code
AbstractAutoProxyCreator#postProcessAfterInitialization
The call to this method takes place after Instantiation, Population is populated, and Initialization is called
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor.BeanFactoryAware {
/**
* Create a proxy with the configured interceptors if the bean is
* identified as one to proxy by the subclass.
* @see #getAdvicesAndAdvisorsForBean
*/
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
if(bean ! =null) {
// Parse beanName at the beginning of getEarlyBeanReference
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// Check if earlyProxyReferences already exists and skip returning the original bean object if the proxy object was created in getEarlyBeanReference to avoid creating it twice
if (!this.earlyProxyReferences.contains(cacheKey)) {
// Use dynamic proxy technology to generate proxy objects
returnwrapIfNecessary(bean, beanName, cacheKey); }}returnbean; }}Copy the code
There are still many things that have not been introduced, such as BeanPostProcessor inheritance system, such as createBeanInstance instance bean analysis, such as populateBean dependency injection analysis, For example, initializeBean initialization bean analysis, such as AOP to create a proxy object specific process, so give this article a core is the main singleton bean creation process, as well as loop dependency solution process, why need level 3 cache rather than level 2 cache.
Finally, introduce a SAO interface:
SingletonTargetSource
target
SingletonTargetSource
getTargetSource()
target
target