This is the first day of my participation in the August Challenge. For details, see:August is more challenging

1. Analysis of Bean instantiation process

// Bean instantiation entry
/ / # finishBeanFactoryInitialization AbstractApplicationContext 】 【 method
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // Initialize the text conversion service
   	// Omit part of the code...

    // Set the Bean factory to a frozen state, indicating that modifications are not allowed
    beanFactory.freezeConfiguration();

    // Instantiate a singleton Bean, which is a non-abstract, non-lazily loaded, singleton Bean
    beanFactory.preInstantiateSingletons();
}

public Object getBean(String name) throws BeansException {
    // Get an instance of the Bean
    return doGetBean(name, null.null.false);
}

// 【AbstractBeanFactory】# doGetBean()
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
    // remove the &prefix BeanFactoryUtils#transformedBeanName from the name. For scenarios that get MyFactoryBean itself,
    // You need to remove the & prefix to get the real beanName, otherwise you get the FactoryBean itself
    final String beanName = transformedBeanName(name);
    Object bean;

    // Try to get the bean instance from the singleton cache
    Object sharedInstance = getSingleton(beanName);
    if(sharedInstance ! =null && args == null) { 
        // If you get the singleton bean, go to the following code
        // If the fetched Bean instance is a Bean instance of FactoryBean, then an object instance needs to be generated from the FactoryBean instance.
        // We need to call FactoryBean.getobject to create the instance object
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    } else {
        // If the singleton bean is not obtained, go to the following code
        // If a circular reference to a prototype-pattern Bean occurs, it is not handled directly and an exception is thrown
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }
        // The parent factory processing, check whether the bean definition exists and other functions are temporarily omitted
        // If beanName exists in parentBeanFactory, return the bean in the parent container
        try {
            // Get the BeanDefinition object for the bean to be instantiated
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            // Check whether the BeanDefinition object corresponds to an abstract Bean
            checkMergedBeanDefinition(mbd, beanName, args);

            // Initialize the beans that the current bean depends on
            String[] dependsOn = mbd.getDependsOn();
            if(dependsOn ! =null) {
                for (String dep : dependsOn) {
                    if (isDependent(beanName, dep)) {
                        throw new BeanCreationException();
                    }
                    registerDependentBean(dep, beanName);
                    try {
                        // getBean() recursively calls doGetBean() to ensure that all dependent beans are initializedgetBean(dep); }}}// Create bean instance.
            // If the Bean is a singleton, please use the following code
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        // The main method to create a singleton Bean
                        returncreateBean(beanName, mbd, args); }});// If the bean is a FactoryBean, then call factoryBean.getobject () to create an instance of the bean
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            } else if (mbd.isPrototype()) {
                // Ignore this section of code
            } else {
                // Ignore this section of code}}}// Omit part of the code...
    return (T) bean;
}

// Core method
/ / # createBean AbstractAutowireCapableBeanFactory 】 【 () method
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
    RootBeanDefinition mbdToUse = mbd;
    // Resolve the class based on the set class attribute or classNameClass<? > resolvedClass = resolveBeanClass(mbd, beanName);if(resolvedClass ! =null&&! mbd.hasBeanClass() && mbd.getBeanClassName() ! =null) {
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }
    
    try {
        // Handle the lookup-method and replace-method subtags
        mbdToUse.prepareMethodOverrides();
    }
    try {
        // Get the BeanPostProcessor proxy object
        // Give BeanPostProcessors the chance to return a proxy instead of an instance of the bean
		// Before initialization, apply the post-processor to resolve whether the specified bean has been short-circuited before initialization
        / / execution InstantiationAwareBeanPostProcessor. PostProcessBeforeInstantiation -- -- bean instantiation pre-processing
10      / / execution InstantiationAwareBeanPostProcessor. PostProcessAfterInitialization -- -- bean initializes the post processing
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        if(bean ! =null) {
            returnbean; }}try {
        // Finish creating the Bean instance (instantiate, populate, initialize)
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        returnbeanInstance; }}Copy the code

1.1 Resolve the corresponding class based on the bean name

// Parse the class by setting the class property or by className: call AbstractBeanFactory class
protectedClass<? > resolveBeanClass(final RootBeanDefinition mbd, String beanName, finalClass<? >... typesToMatch) {try {
        if (mbd.hasBeanClass()) {
            return mbd.getBeanClass();
        }
        if(System.getSecurityManager() ! =null) {
            returnAccessController.doPrivileged((PrivilegedExceptionAction<Class<? >>) () -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext()); }else {
            returndoResolveBeanClass(mbd, typesToMatch); }}}privateClass<? > doResolveBeanClass(RootBeanDefinition mbd, Class<? >... typesToMatch)throws ClassNotFoundException {
    // Omit part of the code....
    String className = mbd.getBeanClassName();
    if(className ! =null) {
        Object evaluated = evaluateBeanDefinitionString(className, mbd);
        if(! className.equals(evaluated)) {// A dynamically resolved expression, supported as of 4.2...
            if (evaluated instanceof Class) {
                return(Class<? >) evaluated; }else if (evaluated instanceof String) {
                returnClassUtils.forName((String) evaluated, classLoaderToUse); }}if(classLoaderToUse ! = beanClassLoader) {returnClassUtils.forName(className, classLoaderToUse); }}return mbd.resolveBeanClass(beanClassLoader);
}
Copy the code

1.2 Processing the lookup-metod and replace-method subtags

// The method that validates and prepares the Override is the Override method
public void prepareMethodOverrides(a) throws BeanDefinitionValidationException {
    if (hasMethodOverrides()) {
        Set<MethodOverride> overrides = getMethodOverrides().getOverrides();
        synchronized (overrides) {
            for(MethodOverride mo : overrides) { prepareMethodOverride(mo); }}}}protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
    // Get the number of methods for the corresponding class
    int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
    if (count == 0) {
        throw new BeanDefinitionValidationException(
            "Invalid method override: no method with name '" + mo.getMethodName() +
            "' on class [" + getBeanClassName() + "]");
    }
    else if (count == 1) {
        // The token MethodOverride is not overridden, avoiding the overhead of parameter type checking
        mo.setOverloaded(false); }}/ / summary:
// The lookup-method and replace-method subtags are parsed into the methodOverrides property of the BeanDefinition object, indicating that they need to be override
// Cover the method; So these two tags need to be parsed before creating the bean, but only preprocessing.
PrepareMethodOverride (MethodOverride mo) prepareMethodOverride(MethodOverride mo) prepareMethodOverride(MethodOverride mo) If there are multiple overloaded methods in a class,
// When calling or enhancing, you also need to parse the parameter types to determine which method is being called. Spring places some functions here for pre-processing if there is only one method
// A method is not overloaded. When called later, you can directly find the method to call, and do not have to parse the parameters to determine the method, so you can avoid some of the parameter type checking overhead
Copy the code

1.3 Processing Post-processing before initialization

// Get the BeanPostProcessor proxy object
// Note: AbstractAutoProxyCreator AOP proxy creation decision is here, this abstract class is implemented
/ / SmartInstantiationAwareBeanPostProcessor, inherited the former InstantiationAwareBeanPostProcessor
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
// Not null, short circuit return directly
if(bean ! =null) {
    return bean;
}
/ / if postProcessBeforeInstantiation () returns a value is empty, then enter the upper caller createBean () method,
// Continue to call the doCreateBean() method to complete the object instantiation (creating the object) and the object initialization.

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    if(! Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {/ / first of all, determine whether there is any InstantiationAwareBeanPostProcessor interface processor
        / / if present, indicates that the call is InstantiationAwareBeanPostProcessor postProcessBeforeInstantiation instantiate ()
        // The pre-processing method, which is executed before the Bean object is generated (during the instantiation process).
        // (Note: the "Bean is not generated" means that the Bean does not go through the process defined by Spring to create the Bean, that is, the doCreateBean() method.)
        if(! mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { Class<? > targetType = determineTargetType(beanName, mbd);if(targetType ! =null) {
                bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                if(bean ! =null) {
                    / / if postProcessBeforeInstantiation () returns the object is not null, means that the Bean object already exists.
                    / / object initialization has been completed, and then call postProcessAfterInitialization () to initialize the post processor,
                    // Complete the operation on the Bean object.bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } mbd.beforeInstantiationResolved = (bean ! =null);
    }
    return bean;
}
Copy the code

1.4 Actually creating beans

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, 
                              final @Nullable Object[] args) throws BeanCreationException {
    // The wrapper class of the bean that is finally returned
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        // If it is a singleton, check whether it was previously created in the factory cache
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    // Bean initialization first step: default call to construct an instantiated bean with no parameters
    // Create bean, factory method, constructor, default constructor, etc
    // Construct parameter dependency injection, which occurs in this step
    if (instanceWrapper == null) {
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    // The instantiated Bean object
    finalObject bean = instanceWrapper.getWrappedInstance(); Class<? > beanType = instanceWrapper.getWrappedClass();if(beanType ! = NullBean.class) { mbd.resolvedTargetType = beanType; }synchronized (mbd.postProcessingLock) {
        if(! mbd.postProcessed) {try {
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            }
            mbd.postProcessed = true; }}// Key steps to resolve circular dependencies
    // Check whether circular dependencies are singletons && whether circular dependencies are allowed && whether the current bean is being created
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                                      isSingletonCurrentlyInCreation(beanName));
    // If the singleton Bean needs to be exposed in advance, put it into the level-three cache
    if (earlySingletonExposure) {
        SingleFactories (key is beanName, value is FactoryBean)
        // To avoid late cyclic dependencies, add the factory that created the bean to the cache before the bean is initialized.
        // If other beans depend on this bean, retrieve the corresponding factory creation collection from the cache and resolve the circular dependency. Note that only singletons can do this
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }

    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        // Bean initialization step 2: fill properties (DI dependency injection occurs in this step)
        populateBean(beanName, mbd, instanceWrapper);
        // Bean initialization step 3: Complete bean initialization by calling the initialization method (AOP occurs in this step)
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
	// Is not null only if a cyclic dependency is detected
    if (earlySingletonExposure) {
        Object earlySingletonReference = getSingleton(beanName, false);
        // Circular dependencies exist
        if(earlySingletonReference ! =null) {
            // If exposedObject is not changed in the initialization method, it is not enhanced
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            }
            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                String[] dependentBeans = getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
                    // Check dependencies
                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                        actualDependentBeans.add(dependentBean);
                    }
                }
                // when a bean is created, it must bean actualDependentBeans
                // If this parameter is not empty, it indicates that the dependent bean has not been created
                if(! actualDependentBeans.isEmpty()) {throw new BeanCurrentlyInCreationException(""); }}}}// Register the bean according to score
    try {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }

    return exposedObject;
}
Copy the code

1.4.1 Creating bean Instances

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
    // Get the class corresponding to the beanClass<? > beanClass = resolveBeanClass(mbd, beanName);// If the factory method is not empty, it is created using the factory method
	if(mbd.getFactoryMethodName() ! =null)  {
		return instantiateUsingFactoryMethod(beanName, mbd, args);
	}
	boolean resolved = false;
	boolean autowireNecessary = false;
	if (args == null) {
		synchronized (mbd.constructorArgumentLock) {
            // A class has multiple constructors with different arguments, so before calling, you need to parse out the constructor based on the arguments.
            // Cache is used here. If the constructor has been parsed before, use it directly here.
			if(mbd.resolvedConstructorOrFactoryMethod ! =null) {
				resolved = true; autowireNecessary = mbd.constructorArgumentsResolved; }}}if (resolved) {
		if (autowireNecessary) {
            // The constructor is automatically injected
			return autowireConstructor(beanName, mbd, null.null);
		}
		else {
            // The default constructor automatically injects
			returninstantiateBean(beanName, mbd); }}// Parse the constructorConstructor<? >[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);if(ctors ! =null|| mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || ! ObjectUtils.isEmpty(args)) {// The constructor is automatically injected
		return autowireConstructor(beanName, mbd, ctors, args);
	}
    // The default constructor automatically injects
	return instantiateBean(beanName, mbd);
}
Copy the code

1.4.1.1 Factory method creation

// Get the class corresponding to the beanClass<? > beanClass = resolveBeanClass(mbd, beanName);// If the factory method is not empty, it is created using the factory method
if(mbd.getFactoryMethodName() ! =null)  {
    return instantiateUsingFactoryMethod(beanName, mbd, args);
}
Copy the code

1.4.1.2 Constructor with parameter creation

public BeanWrapper autowireConstructor(final String beanName, finalRootBeanDefinition mbd, Constructor<? >[] chosenCtors,final Object[] explicitArgs) {

	BeanWrapperImpl bw = new BeanWrapperImpl();
	this.beanFactory.initBeanWrapper(bw); Constructor<? > constructorToUse =null;
	ArgumentsHolder argsHolderToUse = null;
	Object[] argsToUse = null;
    // The explicitArgs argument is passed through the getBean() method, Object getBean(String name, Object... args)
	if(explicitArgs ! =null) {
        // If the getBean method is passed in parameters, use it directly
		argsToUse = explicitArgs;
	}
	else {
        // If no parameters are passed to the getBean method, it is parsed from the configuration file
		Object[] argsToResolve = null;
        // Fetch from the cache
		synchronized(mbd.constructorArgumentLock) { constructorToUse = (Constructor<? >) mbd.resolvedConstructorOrFactoryMethod;if(constructorToUse ! =null && mbd.constructorArgumentsResolved) {
				argsToUse = mbd.resolvedConstructorArguments;
				if (argsToUse == null) { argsToResolve = mbd.preparedConstructorArguments; }}}if(argsToResolve ! =null) {
            // Configure the constructor parametersargsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve); }}// The construct is not cached and needs to be parsed
	if (constructorToUse == null) {
		booleanautowiring = (chosenCtors ! =null || mbd.getResolvedAutowireMode() == 
                              							RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
		ConstructorArgumentValues resolvedValues = null;
        // Number of parameters
		int minNrOfArgs;
		if(explicitArgs ! =null) {
			minNrOfArgs = explicitArgs.length;
		}
		else {
            // Get the constructor parameters configured in the configuration file
			ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
			resolvedValues = new ConstructorArgumentValues();
            // Get the number of parametersminNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues); } Constructor<? >[] candidates = chosenCtors;if (candidates == null) { Class<? > beanClass = mbd.getBeanClass(); candidates = (mbd.isNonPublicAccessAllowed() ? beanClass.getDeclaredConstructors() : beanClass.getConstructors()); }// The sort constructor, which sorts by number of parameters
		AutowireUtils.sortConstructors(candidates);
		intminTypeDiffWeight = Integer.MAX_VALUE; Set<Constructor<? >> ambiguousConstructors =null;
		for(Constructor<? > candidate : candidates) { Class<? >[] paramTypes = candidate.getParameterTypes();if(constructorToUse ! =null && argsToUse.length > paramTypes.length) {
				// If a constructor that satisfies the condition has been found, the constructor terminates
				break;
			}
			if (paramTypes.length < minNrOfArgs) {
				continue;
			}
			ArgumentsHolder argsHolder;
			if(resolvedValues ! =null) {
                // The name of the constructor parameter
				String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
			    if (paramNames == null) {
                    // If the parameter name is empty, get the parameter name explorer
					ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
					if(pnd ! =null) {
                        // Use explorer to get the parameter names of the corresponding constructor
					   paramNames = pnd.getParameterNames(candidate);
					}
                    // Create a parameter holder based on the parameter name and type
				argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, 
                                         paramNames,getUserDeclaredConstructor(candidate), autowiring);
			}
			else {
				// The constructor has no parameters
				argsHolder = new ArgumentsHolder(explicitArgs);
			}
            // Check for the presence of uncertain constructors, such as parent-child relationships
			int typeDiffWeight = (mbd.isLenientConstructorResolution() 
                                  	? argsHolder.getTypeDifferenceWeight(paramTypes) 
                                  	: argsHolder.getAssignabilityWeight(paramTypes));
			if (typeDiffWeight < minTypeDiffWeight) {
				constructorToUse = candidate;
				argsHolderToUse = argsHolder;
				argsToUse = argsHolder.arguments;
				minTypeDiffWeight = typeDiffWeight;
				ambiguousConstructors = null;
			}
			else if(constructorToUse ! =null && typeDiffWeight == minTypeDiffWeight) {
				if (ambiguousConstructors == null) {
					ambiguousConstructors = newLinkedHashSet<Constructor<? > > (); ambiguousConstructors.add(constructorToUse); } ambiguousConstructors.add(candidate); }}if (constructorToUse == null) {
			throw new BeanCreationException("...")}// Add the parsed constructor to the cache
		if (explicitArgs == null) { argsHolderToUse.storeCache(mbd, constructorToUse); }}/ / instantiate
	Object beanInstance;
	if(System.getSecurityManager() ! =null) {
		finalConstructor<? > ctorToUse = constructorToUse;final Object[] argumentsToUse = argsToUse;
		beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
			public Object run(a) {
				return beanFactory.getInstantiationStrategy().instantiate(
						mbd, beanName, beanFactory, ctorToUse, argumentsToUse);
			}
		}, beanFactory.getAccessControlContext());
	}
	else {
		beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
				mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
	}
	bw.setBeanInstance(beanInstance);
	return bw;
}
Copy the code

1.4.1.3 Default constructor created

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
    try {
        Object beanInstance;
        final BeanFactory parent = this;
        if(System.getSecurityManager() ! =null) {
            beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
           						getInstantiationStrategy().instantiate(mbd, beanName, parent), 		
                                                      		getAccessControlContext());
        }
        else {
            beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
        }
        BeanWrapper bw = new BeanWrapperImpl(beanInstance);
        initBeanWrapper(bw);
        returnbw; }}public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner,
		finalConstructor<? > ctor, Object... args) {
    // If there are no methods that need to be changed dynamically, instantiate them directly using reflection
	if (bd.getMethodOverrides().isEmpty()) {
		if(System.getSecurityManager() ! =null) {
			AccessController.doPrivileged(new PrivilegedAction<Object>() {
				@Override
				public Object run(a) {
					ReflectionUtils.makeAccessible(ctor);
					return null; }}); }// Use reflection to instantiate
		return BeanUtils.instantiateClass(ctor, args);
	}
	else {
        // If override or dynamic replacement methods are needed, then CGLIB is needed for dynamic proxies. When creating proxies, we can enhance our embedded code
		returninstantiateWithMethodInjection(bd, beanName, owner, ctor, args); }}Copy the code

1.4.2 Adding a factory cache for singleton objects

// Key steps to resolve circular dependencies
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                                  isSingletonCurrentlyInCreation(beanName));
// If the singleton Bean needs to be exposed in advance, put it into the level-three cache
if (earlySingletonExposure) {
    SingletonFactories (key is beanName, value is FactoryBean)
    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

protected void addSingletonFactory(String beanName, ObjectFactory
        singletonFactory) {
    Assert.notNull(singletonFactory, "Singleton factory must not be null");
    synchronized (this.singletonObjects) {
        // If there is no change instance in the level 1 cache, put it in the level 3 cache
        if (!this.singletonObjects.containsKey(beanName)) {
            // Put it into the level 3 cache
            this.singletonFactories.put(beanName, singletonFactory);
            // Remove from the secondary cache
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName); }}}Copy the code

1.4.3 Populating various properties of an object

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
    if (bw == null) {
        if (mbd.hasPropertyValues()) {
            throw new BeanCreationException();
        }
        else {
            // Skip property population phase for null instance.
            return; }}/ / to InstantiationAwareBeanPostProcessors last chance before the property into modify Bean property values
	boolean continueWithPropertyPopulation = true;
	if(! mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                / / by calling the specific postProcessAfterInstantiation method, if the call returns false, said don't need to continue the dependency injection, returned directly
				if(! ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation =false;
					break; }}}}if(! continueWithPropertyPopulation) {return;
	}
    }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
	PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

    // The default is 0, which means that all dependency injection needs to be explicitly configured in the XML file
    // If the related dependency assembly mode is set, the properties of the Bean will be traversed to complete the corresponding injection by type or name, no additional configuration is required
	if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
			mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
		MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
        // Name injection
		if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
			autowireByName(beanName, mbd, bw, newPvs);
		}
        // Type injection
		if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
			autowireByType(beanName, mbd, bw, newPvs);
		}
		pvs = newPvs;
	}
    / / container whether registered its rear InstantiationAwareBeanPostProcessor processor
	boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    // Requires dependency checking
	booleanneedsDepCheck = (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 ibp = (InstantiationAwareBeanPostProcessor) bp;
                	// Post all attributes that need to be checked for dependencies
					pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), 
                                                        	beanName);
					if (pvs == null) {
						return; }}}}if(needsDepCheck) { checkDependencies(beanName, mbd, filteredPds, pvs); }}// Apply attributes to the bean
	applyPropertyValues(beanName, mbd, bw, pvs);
}
Copy the code

1.4.3.1 Name injection

protected void autowireByName( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
   // Get an array of attribute names that are not simple types
   // According to the PropertyDescriptors of BW, iterate over all PropertyValues that are writable (that is, set method exists) in the BeanDefinition,
   // This is not a simple attribute name. Simple attributes are determined by referring to the following methods, mainly covering the basic type and its wrapper class, Number, Date, etc
   String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
   for (String propertyName : propertyNames) {
      if (containsBean(propertyName)) {
         // Get the corresponding Bean instance by name
         Object bean = getBean(propertyName);
         // Set non-simple type attributespvs.add(propertyName, bean); registerDependentBean(propertyName, beanName); }}}// Simple type determination
public static boolean isSimpleValueType(Class
        clazz) {
	return ClassUtils.isPrimitiveOrWrapper(clazz) || clazz.isEnum() ||
			CharSequence.class.isAssignableFrom(clazz) ||
			Number.class.isAssignableFrom(clazz) ||
			Date.class.isAssignableFrom(clazz) ||
			clazz.equals(URI.class) || clazz.equals(URL.class) ||
			clazz.equals(Locale.class) || clazz.equals(Class.class);
}
Copy the code

1.4.3.2 Type injection

protected void autowireByType( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

    TypeConverter converter = getCustomTypeConverter();
    if (converter == null) {
        converter = bw;
    }

    Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
    String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    for (String propertyName : propertyNames) {
        try {
            PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
            // Don't try autowiring by type for type Object: never makes sense,
            // even if it technically is a unsatisfied, non-simple property.
            if(Object.class ! = pd.getPropertyType()) { MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);// Do not allow eager init for type matching in case of a prioritized post-processor.
                booleaneager = ! PriorityOrdered.class.isInstance(bw.getWrappedInstance()); DependencyDescriptor desc =new AutowireByTypeDependencyDescriptor(methodParam, eager);
                // This is the dependent assembly type based on the input type passed in desc
				// Look for a BeanName in BeanFacoty that has the same class or parent
				// Finally get or initialize the corresponding class according to the BeanName, and then fill the autowiredBeanNames with all the beannames that meet the condition
                Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, 		
                                                             converter);
                if(autowiredArgument ! =null) {
                    pvs.add(propertyName, autowiredArgument);
                }
                for(String autowiredBeanName : autowiredBeanNames) { registerDependentBean(autowiredBeanName, beanName); } autowiredBeanNames.clear(); }}}}Copy the code

1.4.4 Processing the init-method method

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    if(System.getSecurityManager() ! =null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            invokeAwareMethods(beanName, bean);
            return null;
        }, getAccessControlContext());
    }
    else {
        invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    if (mbd == null| |! mbd.isSynthetic()) {/ / application BeanPostProcessor postProcessBeforeInitialization method
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        // Execute the initialization method (after calling the afterPropertiesSet of the InitializingBean, then calling the initialization method specified in the Init-method property)
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    if (mbd == null| |! mbd.isSynthetic()) {/ / the BeanPostProcessor postProcessAfterInitialization method (AOP proxy objects generated)
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}
Copy the code

1.4.4.1 Front processor for handling beans

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException {
	/ / get all BeanPostProcessor in the container, perform its postProcessBeforeInitialization method
    / / (@ PostConstruct annotations specified initialization method, it is at this step by CommonAnnotationBeanPostProcessor implementation)
    / / implementation ApplicationContextAwareProcessor ApplicationContextAware interface beans will call
    / / postProcessBeforeInitialization method, Finally implement the setApplicationContext assignment call to the interface (then the system can dynamically obtain the desired bean object via the assigned // applicationContext getBean method)
    Object result = existingBean;
    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
        Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}
Copy the code

1.4.4.2 Executing the init-method method

protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {
    boolean isInitializingBean = (bean instanceof InitializingBean);
    // If it is an implementation class of the InitializingBean interface, initialize the implementation class of the InitializingBean first
    if (isInitializingBean && (mbd == null| |! mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
        if(System.getSecurityManager() ! =null) {
            try {
                AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                    ((InitializingBean) bean).afterPropertiesSet();
                    return null; }, getAccessControlContext()); }}else {
            // Call the afterPropertiesSet method of the InitializingBean interface((InitializingBean) bean).afterPropertiesSet(); }}// Then initialize the method in the init-method property of the 
      
        tag
      
    if(mbd ! =null&& bean.getClass() ! = NullBean.class) { String initMethodName = mbd.getInitMethodName();if(StringUtils.hasLength(initMethodName) && ! (isInitializingBean &&"afterPropertiesSet".equals(initMethodName)) && ! mbd.isExternallyManagedInitMethod(initMethodName)) {// Call the custom initialization methodinvokeCustomInitMethod(beanName, bean, mbd); }}}Copy the code

1.4.4.3 Post-processor for processing beans

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {
	/ / configure the instance or AOP of things here will call AbstractAutoProxyCreator postProcessAfterInitialization method in a class,
    // Create the proxy object and cache it. (Then, when the system needs to access the instance, it will get the proxy object and access the instance function of the object through the proxy object.)
    Object result = existingBean;
    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
        Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}
Copy the code

1.5 Bean Lifecycle Description

  1. Instantiate the Instantiation
  2. Property to the value Populate
  3. Initialize the Initialization
  4. Destruction of Destruction

Instantiate -> Attribute assignment -> Initialize -> Destroy

2, Spring AOP principle analysis

2.1 Analysis of program entry

// Let's go back to the previous article to parse BeanDefinition
/ / BeanDefinitionParserDelegate# parseCustomElement method, find specific tags, such as < aop: config > < aop: autoproxy >, etc., to get to
// The corresponding NameSpaceHandler is AopNameSpaceHandler
public class AopNamespaceHandler extends NamespaceHandlerSupport {
    / / this method will be invoked in the DefaultNamespaceHandlerResolver resolve method of a class
    @Override
    public void init(a) {
        // 
      
        registerBeanDefinitionParser("config".new ConfigBeanDefinitionParser());
        registerBeanDefinitionParser("aspectj-autoproxy".new AspectJAutoProxyBeanDefinitionParser());
        registerBeanDefinitionDecorator("scoped-proxy".new ScopedProxyBeanDefinitionDecorator());

        // Only in 2.0 XSD: moved to context namespace as of 2.1
        registerBeanDefinitionParser("spring-configured".newSpringConfiguredBeanDefinitionParser()); }}/ / find AspectJAutoProxyBeanDefinitionParser# parse
public BeanDefinition parse(Element element, ParserContext parserContext) {
    AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
    extendBeanDefinition(element, parserContext);
    return null;
}

/ / into the registerAspectJAnnonationAutoProxyCreatorIfNecessary method
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary( ParserContext parserContext, Element sourceElement) {
    // Register AutoProxyCreator with the name beanDefinition of internalAutoProxyCreator
    BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
        parserContext.getRegistry(), parserContext.extractSource(sourceElement));
    // For proxy-target-class (forcing cGlib) and exposer-proxy (whether to expose the proxy interface) properties
    useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
    // Register the component and notify it for further processing by the listener
	/ / which beanDefinition for AnnotationAwareAspectJAutoProxyCreator className
    registerComponentIfNecessary(beanDefinition, parserContext);
}

/ / for the realization of AOP, basically all is by AnnotationAwareAspectJAutoProxyCreator to complete, it can automatically according to the tangent Point of the @ Point annotations define the agent
// The matching bean. But for the sake of easy configuration, Spring using a custom configuration to help us register AnnotationAwareAspectJAutoProxyCreator automatically.

//
/ / AnnotationAwareAspectJAutoProxyCreator derived class AbstractAutoProxyCreator and AbstractAutoProxyCreator has been realized
/ / the BeanPostProcessor interface

public interface BeanPostProcessor {
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException; } Entry analysis:/ / the entrance 1: before the object instantiation: AbstractAutoProxyCreator. PostProcessBeforeInstantiation
try {
    // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
    // Give BeanPostProcessors a chance to create a proxy object. If the proxy object returns something other than empty, then createBean returns directly.
    // The target object is no longer instantiated.
    Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    if(bean ! =null) {
        returnbean; }}/ / resolveBeforeInstantiation essence is invoked here call of nature
// AbstractAutoProxyCreator.applyBeanPostProcessorsBeforeInstantiation
public Object postProcessBeforeInstantiation(Class
        beanClass, String beanName) throws BeansException {
    Object cacheKey = getCacheKey(beanClass, beanName);
    if(! StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
        if (this.advisedBeans.containsKey(cacheKey)) {
            return null;
        }
        // 1. Some objects that can't be proxyedbase classes: Advices, Advisors and AopInfrastructureBeans;
        // Class with AOP annotations: @aspect
        // 2. Subclasses can copy the class. ShouldSkip returns true if some cases do not need to be represented
        if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return null; }}// Get the targetSource and, if it exists, create the proxy directly before the object is initialized, avoiding unnecessary instantiation of the target object
    TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
    // Create a proxy object here if you have a custom targetSource
    // The benefit of this is that the objects being proxied can be changed dynamically, instead of just one target object
    // (You can proxy objects in the object pool, you can create a new object every time you create a proxy)
    if(targetSource ! =null) {
        if (StringUtils.hasLength(beanName)) {
            this.targetSourcedBeans.add(beanName);
        }
        // Get the Advisors, which are left to the subclass to implement
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
        Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
        this.proxyTypes.put(cacheKey, proxy.getClass());
        // Return the object of the proxy
        return proxy;
    }

    return null;
}

// AbstractAutoProxyCreator (AOP) : AbstractAutoProxyCreator (AOP) : AbstractAutoProxyCreator (AOP) : AbstractAutoProxyCreator)
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if(bean ! =null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName); 
        // Build a cacheKey based on the given bean and className, of the form beanClassName_beanName
        if (!this.earlyProxyReferences.contains(cacheKey)) {
            // Determine whether an agent is needed
            returnwrapIfNecessary(bean, beanName, cacheKey); }}return bean;
}

// As you can see, after loading the XML AOP-related BeanDefinition definitions and registering them in the container, two situations arise
// 1. If there is a custom TargetSource, the proxy is created before the Bean instance object is created, and the subsequent instantiation process is not performed
// 2. If there is no custom TargetSource, create a default TargetSource (SingletonTargetSource)
// After the Bean instance has been created and initialized, the post handler method is called to create the proxy instance.
Copy the code

2.2 Entry for agent creation

// Entry 1: Proxy creation before object instantiation
protected Object createProxy(Class<? > beanClass,@Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {

    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory,
                                         beanName, beanClass);
    }

    // Create a proxy factory object
    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.copyFrom(this);

    // If the CGLib proxy is not used
    if(! proxyFactory.isProxyTargetClass()) {// Whether it is possible to use the CGLib proxy
        if (shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        }
        else {
            / / see if beanClass corresponding class contains InitializingBean. The class/DisposableBean class/Aware. The class interface
            // If no, use JDK dynamic proxy; if yes, use CGLib dynamic proxyevaluateProxyInterfaces(beanClass, proxyFactory); }}// Get all associated Advisor collections (branch to be added)
    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    proxyFactory.addAdvisors(advisors);
    // Here the targetSource is usually SingletonTargetSource
    proxyFactory.setTargetSource(targetSource);
    // Empty implementation
    customizeProxyFactory(proxyFactory);
    proxyFactory.setFrozen(this.freezeProxy);
    // Whether to set the pre-filter mode, which is true for this article
    if (advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }
    // Get the object generated using the JDK dynamic proxy or cGLIb dynamic proxy
    return proxyFactory.getProxy(getProxyClassLoader());
}

// Entry 2: Created after the object is instantiated and initialized
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    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 agent
    // and not proxying beanName as an aspect name within AOP
    // See the shouldSkip() method for subclass overwrite
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    // Create proxy if we have advice.
    // Find the set of Advisor objects that are relevant to the proxy class, which is relevant here with the ponit-cut expression
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

    // Take an agent only if the corresponding Advisor is not null
    if(specificInterceptors ! = DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE);
        // Generate proxy objects using JDK dynamic proxy or CGLIb dynamic proxy
        Object proxy = createProxy(
            bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        // Put the proxy type cache
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }
    // Put the notification cache
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}

Protected Object createProxy(...) Method, both of which complete the broker creation process
Copy the code

2.3 Interpretation of Agent Types

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    if(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<? > targetClass = config.getTargetClass();if (targetClass == null) {
            throw new AopConfigException("TargetSource cannot determine target class: " +
                                         "Either an interface or a target is required for proxy creation.");
        }
        // If the target class is an interface or a subclass of Proxy, use JDK dynamic Proxy
        if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
            return new JdkDynamicAopProxy(config);
        }
        // Use the Cglib dynamic proxy
        return new ObjenesisCglibAopProxy(config);
    }
    else {
        // Use JDK dynamic proxy by default
        return newJdkDynamicAopProxy(config); }}// JdkDynamicAopProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
    if (logger.isDebugEnabled()) {
        logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource()); } Class<? >[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

// CglibAopProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
    try{ Class<? > rootClass =this.advised.getTargetClass();
        // Omit part of the code....
        // Configure CGLIB Enhancer...
        Enhancer enhancer = createEnhancer();
        if(classLoader ! =null) {
            enhancer.setClassLoader(classLoader);
            if (classLoader instanceof SmartClassLoader &&
                ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
                enhancer.setUseCache(false);
            }
        }
        enhancer.setSuperclass(proxySuperClass);
        enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
        enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
        enhancer.setStrategy(newClassLoaderAwareUndeclaredThrowableStrategy(classLoader)); Callback[] callbacks = getCallbacks(rootClass); Class<? >[] types =newClass<? >[callbacks.length];for (int x = 0; x < types.length; x++) {
            types[x] = callbacks[x].getClass();
        }
        // fixedInterceptorMap only populated at this point, after getCallbacks call above
        enhancer.setCallbackFilter(new ProxyCallbackFilter(
            this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, 
            this.fixedInterceptorOffset));
        enhancer.setCallbackTypes(types);

        // Generate the proxy class and create a proxy instance.
        returncreateProxyClassAndInstance(enhancer, callbacks); }}protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
    enhancer.setInterceptDuringConstruction(false);
    enhancer.setCallbacks(callbacks);
    return (this.constructorArgs ! =null && this.constructorArgTypes ! =null ?
            enhancer.create(this.constructorArgTypes, this.constructorArgs) :
            enhancer.create());
}


/ / summary:
// 1, proxy-target-class is not configured or proxy-target-class= "false", returns JdkDynamicAopProxy
// 2, proxy-target-class="true" or the object does not implement any interface or only implements SpringProxy interface, return CglibAopProxy
Copy the code

2.4 Implementation of JDK dynamic proxy invocation

// Finally, the proxy object is generated. After the proxy object is generated, the method is called, because the JdkDynamicAopProxy itself implements the InvocationHandler interface
// The processing logic is in the JdkDynamicAopProxy class invoke method
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    MethodInvocation invocation;
    Object oldProxy = null;
    boolean setProxyContext = false;

    TargetSource targetSource = this.advised.targetSource;
    Object target = null;

    try {
        // Run the JdkDynamicAopProxy method if the proxy object is equal.
        Spring does not intercept the EQUAL method with AOP
        if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
            // The target does not implement the equals(Object) method itself.
            return equals(args[0]);
        }
        // Execute the JdkDynamicAopProxy method if the target object to be proxied is hashcode.
        Spring also does not intercept Hashcode with AOP
        else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
            // The target does not implement the hashCode() method itself.
            return hashCode();
        }
        else if (method.getDeclaringClass() == DecoratingProxy.class) {
            // There is only getDecoratedClass() declared -> dispatch to proxy config.
            return AopProxyUtils.ultimateTargetClass(this.advised);
        }
        // If the proxy target object implements the Advised interface, execute the target object's methods directly using reflection. No enhancement.
        else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                 method.getDeclaringClass().isAssignableFrom(Advised.class)) {
            // Service invocations on ProxyConfig with the proxy config...
            return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
        }

        Object retVal;

        // Advance exposure is required
        if (this.advised.exposeProxy) {
            oldProxy = AopContext.setCurrentProxy(proxy);
            setProxyContext = true;
        }

        // Get the target objecttarget = targetSource.getTarget(); Class<? > targetClass = (target ! =null ? target.getClass() : null);
		
        // Get the intercepting chain of the method
        // In methodCache, if there is an interception chain for this method, the method is returned. If there is no interception chain, the method is called
        // this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass)
        // Get the method intercept chain, put it in the cache, and return the following logic for this method
        // 1. Traverse the Advisor
		// 2. If the Advisor is of the PointcutAdvisor type: Get the Advisor's Pointcut and determine whether the method of the target object to be executed is augmented // by this Advisor. Need to do some testing, if the runtime is to return to the list after joining InterceptorAndDynamicMethodMatcher encapsulation of interceptor. Otherwise just join
        // Interceptor to return list
		// 3. If the Advisor was a IntroducationAdvisor type, use the Advisor's classFilter to determine whether the target object's class was enhanced by the Advisor.
        // If yes, the interceptor is added to the return list
        // 4. If the Advisor is neither a PointcutAdvisor type nor a IntroducationAdvisor type, generate an interceptor and add it to the return without matching
        / / back to the list
        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

        // Check if we have any announcements. If we don't, we can make the reflection invocation directly on the target class, avoiding creating the MethodInvocation class
        // Call the method of the target class
        if (chain.isEmpty()) {
            Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
            // Invoke the method of the target object through reflection
            retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
        }
        else {
            // We need to create a method call
            invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
            // Access the connection point through the interceptor chain
            retVal = invocation.proceed();
        }

        // The value returned by the processing methodClass<? > returnType = method.getReturnType();if(retVal ! =null&& retVal == target && returnType ! = Object.class && returnType.isInstance(proxy) && ! RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { retVal = proxy; }else if (retVal == null&& returnType ! = Void.TYPE && returnType.isPrimitive()) {throw new AopInvocationException(
                "Null return value from advice does not match primitive return type for: " + method);
        }
        returnretVal; }}Copy the code