directory

  1. Instantiation of a Bean
  2. An overview of the process
  3. Source code analysis

3.1 Overview of createBeanInstance 3.1 Using the Supplier Interface 3.2 Instantiating the FactoryMethod Method 3.3 Instantiating the Parameter Constructor 3.4 Instantiating the No-parameter Constructor 3.5 Finishing Up after Instantiating the Bean 4. Case 4.1 Using factory method to create bean 4.2 Parameterized Constructor with AutoWired 4.3 Parameterized Constructor without AutoWired 4.4 Parameterless Constructor 5. conclusion

Life needs the passion to explore, the courage to persist, and the power to love life and love yourself.

1. Instantiation of beans

On an article about the bean’s life cycle, the first step involves the instantiation of the bean, bean instantiation, the essay focuses on the analysis into the first source of AbstractAutowireCapableBeanFactory createBeanInstance method in class.

2. Process overview

The diagram above describes the main steps in the bean instantiation process:

  1. If there isSupplierThe callback is calledobtainFromSupplier()Initialize;
  2. If a factory method exists, it is initialized using the factory method.
  3. If the constructor argument is not empty, get firstautowiredIf the argument is a reference type, loop through the container again to fetch it, and finally instantiate it by reflection.
  4. If the constructor takes no arguments, the default no-argument constructor is instantiated.
  5. Finally, add the bean to the level 1 cache and clear the beans from the level 2 and 3 caches.

3. Source code analysis

3.1 createBeanInstance overview

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { // Make sure bean class is actually resolved at this point. Class<? > beanClass = resolveBeanClass(mbd, beanName); if (beanClass ! = null && ! Modifier.isPublic(beanClass.getModifiers()) && ! mbd.isNonPublicAccessAllowed()) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName()); } Supplier<? > instanceSupplier = mbd.getInstanceSupplier(); // Get if (instanceSupplier! = null) { return obtainFromSupplier(instanceSupplier, beanName); } // Instantiate if (mbd.getFactoryMethodName() with the FactoryMethod method. = null) { return instantiateUsingFactoryMethod(beanName, mbd, args); } // Shortcut when re-creating the same bean... boolean resolved = false; boolean autowireNecessary = false; if (args == null) { synchronized (mbd.constructorArgumentLock) { if (mbd.resolvedConstructorOrFactoryMethod ! = null) { resolved = true; autowireNecessary = mbd.constructorArgumentsResolved; } } } if (resolved) { if (autowireNecessary) { return autowireConstructor(beanName, mbd, null, null); } else { return instantiateBean(beanName, mbd); } } // Candidate constructors for autowiring? // The Constructor takes the autowired modifier Constructor<? >[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors ! = null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || ! ObjectUtils.isEmpty(args)) { return autowireConstructor(beanName, mbd, ctors, args); } // Preferred constructors for default construction? ctors = mbd.getPreferredConstructors(); if (ctors ! = null) { return autowireConstructor(beanName, mbd, ctors, null); } // simply use no-arg constructor. // default instantiateBean(beanName, MBD); }Copy the code

3.1 Using the Supplier interface

Supplier<? > instanceSupplier = mbd.getInstanceSupplier(); // Get if (instanceSupplier! = null) { return obtainFromSupplier(instanceSupplier, beanName); }Copy the code

Enter the obtainFromSupplier method

protected BeanWrapper obtainFromSupplier(Supplier<? > instanceSupplier, String beanName) { Object instance; String outerBean = this.currentlyCreatedBean.get(); this.currentlyCreatedBean.set(beanName); Try {// Get instanceSupplier instance = instancesupplier.get (); } finally { if (outerBean ! = null) { this.currentlyCreatedBean.set(outerBean); } else { this.currentlyCreatedBean.remove(); } } if (instance == null) { instance = new NullBean(); } // wrap BeanWrapper BeanWrapper bw = new BeanWrapperImpl(instance); // Initialize BeanWrapper initBeanWrapper(bw); return bw; }Copy the code

The source code shown above is obtained from instanceSupplier, which is a functional interface:

@FunctionalInterface public interface Supplier<T> { /** * Gets a result. * * @return a result */ T get(); } When was the instanceSupplier set? Take a look at RootBeanDefinition: protected BeanWrapper instantiateUsingFactoryMethod( String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) { return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs); }Copy the code

As you can see, instanceSupplier is set when BeanDefinition is initialized, then retrieved from instancesupplier.get (), and finally wrapped as a BeanWrapper object, which is initialized.

If the FactoryMethod is not empty, it is instantiated using the FactoryMethod:

// Instantiate if (mbd.getFactoryMethodName()! = null) { return instantiateUsingFactoryMethod(beanName, mbd, args); } enter instantiateUsingFactoryMethod method below:  protected BeanWrapper instantiateUsingFactoryMethod( String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) { return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs); }Copy the code

Create a ConstructorResolver object first, and then call the instantiateUsingFactoryMethod method, this method is a lot of detail, see the following main steps:

	public BeanWrapper instantiateUsingFactoryMethod(
			String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {

		BeanWrapperImpl bw = new BeanWrapperImpl();
		this.beanFactory.initBeanWrapper(bw);

		Object factoryBean;
		Class<?> factoryClass;
		boolean isStatic;
		// 获取工厂bean
		String factoryBeanName = mbd.getFactoryBeanName();
		// RootBeanDefinition的factory-bean属性不为空
		if (factoryBeanName != null) {
			if (factoryBeanName.equals(beanName)) {
				throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
						"factory-bean reference points back to the same bean definition");
			}
			factoryBean = this.beanFactory.getBean(factoryBeanName);
			if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
				throw new ImplicitlyAppearedSingletonException();
			}
			factoryClass = factoryBean.getClass();
			isStatic = false;
		}
		// RootBeanDefinition的factory-bean属性为空,需要静态方法初始化
		else {
			// It's a static factory method on the bean class.
			if (!mbd.hasBeanClass()) {
				throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
						"bean definition declares neither a bean class nor a factory-bean reference");
			}
			factoryBean = null;
			factoryClass = mbd.getBeanClass();
			isStatic = true;
		}
		// 工厂方法与参数
		Method factoryMethodToUse = null;
		ArgumentsHolder argsHolderToUse = null;
		Object[] argsToUse = null;

		if (explicitArgs != null) {
			argsToUse = explicitArgs;
		}
		else {
			// 首先尝试从缓存中获取参数
			Object[] argsToResolve = null;
			synchronized (mbd.constructorArgumentLock) {
				factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
				if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
					// Found a cached factory method...
					argsToUse = mbd.resolvedConstructorArguments;
					if (argsToUse == null) {
						argsToResolve = mbd.preparedConstructorArguments;
					}
				}
			}
			if (argsToResolve != null) {
				argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
			}
		}

		if (factoryMethodToUse == null || argsToUse == null) {
			// Need to determine the factory method...
			// Try all methods with this name to see if they match the given arguments.
			// 获取工厂类全名
			factoryClass = ClassUtils.getUserClass(factoryClass);

			List<Method> candidates = null;
			if (mbd.isFactoryMethodUnique) {
				if (factoryMethodToUse == null) {
					factoryMethodToUse = mbd.getResolvedFactoryMethod();
				}
				if (factoryMethodToUse != null) {
					candidates = Collections.singletonList(factoryMethodToUse);
				}
			}
			if (candidates == null) {
				candidates = new ArrayList<>();
				Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
				for (Method candidate : rawCandidates) {
					// 如果有static 且为工厂方法,则添加到 candidates 中
					if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
						candidates.add(candidate);
					}
				}
			}

			// 工厂类只有一个工厂方法
			if (candidates.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
				Method uniqueCandidate = candidates.get(0);
				if (uniqueCandidate.getParameterCount() == 0) {
					mbd.factoryMethodToIntrospect = uniqueCandidate;
					synchronized (mbd.constructorArgumentLock) {
						mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
						mbd.constructorArgumentsResolved = true;
						mbd.resolvedConstructorArguments = EMPTY_ARGS;
					}
                                        // 初始化bean
					bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
					return bw;
				}
			}

			// 工厂类有多个工厂方法,按照参数数量降序排列
			if (candidates.size() > 1) {  // explicitly skip immutable singletonList
				candidates.sort(AutowireUtils.EXECUTABLE_COMPARATOR);
			}

			ConstructorArgumentValues resolvedValues = null;
			boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
			int minTypeDiffWeight = Integer.MAX_VALUE;
			Set<Method> ambiguousFactoryMethods = null;

			int minNrOfArgs;
			if (explicitArgs != null) {
				minNrOfArgs = explicitArgs.length;
			}
			else {
				// We don't have arguments passed in programmatically, so we need to resolve the
				// arguments specified in the constructor arguments held in the bean definition.
				if (mbd.hasConstructorArgumentValues()) {
					ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
					resolvedValues = new ConstructorArgumentValues();
					minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
				}
				else {
					minNrOfArgs = 0;
				}
			}

			LinkedList<UnsatisfiedDependencyException> causes = null;
			// 遍历工厂方法
			for (Method candidate : candidates) {
				int parameterCount = candidate.getParameterCount();

				if (parameterCount >= minNrOfArgs) {
					ArgumentsHolder argsHolder;

					Class<?>[] paramTypes = candidate.getParameterTypes();
					if (explicitArgs != null) {
						// Explicit arguments given -> arguments length must match exactly.
						if (paramTypes.length != explicitArgs.length) {
							continue;
						}
						argsHolder = new ArgumentsHolder(explicitArgs);
					}
					else {
						// Resolved constructor arguments: type conversion and/or autowiring necessary.
						try {
							String[] paramNames = null;
							ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
							if (pnd != null) {
								paramNames = pnd.getParameterNames(candidate);
							}
							argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,
									paramTypes, paramNames, candidate, autowiring, candidates.size() == 1);
						}
						catch (UnsatisfiedDependencyException ex) {
							if (logger.isTraceEnabled()) {
								logger.trace("Ignoring factory method [" + candidate + "] of bean '" + beanName + "': " + ex);
							}
							// Swallow and try next overloaded factory method.
							if (causes == null) {
								causes = new LinkedList<>();
							}
							causes.add(ex);
							continue;
						}
					}

					int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
							argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
					// Choose this factory method if it represents the closest match.
					if (typeDiffWeight < minTypeDiffWeight) {
						factoryMethodToUse = candidate;
						argsHolderToUse = argsHolder;
						argsToUse = argsHolder.arguments;
						minTypeDiffWeight = typeDiffWeight;
						ambiguousFactoryMethods = null;
					}
					// Find out about ambiguity: In case of the same type difference weight
					// for methods with the same number of parameters, collect such candidates
					// and eventually raise an ambiguity exception.
					// However, only perform that check in non-lenient constructor resolution mode,
					// and explicitly ignore overridden methods (with the same parameter signature).
					else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&
							!mbd.isLenientConstructorResolution() &&
							paramTypes.length == factoryMethodToUse.getParameterCount() &&
							!Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
						if (ambiguousFactoryMethods == null) {
							ambiguousFactoryMethods = new LinkedHashSet<>();
							ambiguousFactoryMethods.add(factoryMethodToUse);
						}
						ambiguousFactoryMethods.add(candidate);
					}
				}
			}

			if (factoryMethodToUse == null || argsToUse == null) {
				if (causes != null) {
					UnsatisfiedDependencyException ex = causes.removeLast();
					for (Exception cause : causes) {
						this.beanFactory.onSuppressedException(cause);
					}
					throw ex;
				}
				List<String> argTypes = new ArrayList<>(minNrOfArgs);
				if (explicitArgs != null) {
					for (Object arg : explicitArgs) {
						argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
					}
				}
				else if (resolvedValues != null) {
					Set<ValueHolder> valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());
					valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
					valueHolders.addAll(resolvedValues.getGenericArgumentValues());
					for (ValueHolder value : valueHolders) {
						String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) :
								(value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null"));
						argTypes.add(argType);
					}
				}
				String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"No matching factory method found: " +
						(mbd.getFactoryBeanName() != null ?
							"factory bean '" + mbd.getFactoryBeanName() + "'; " : "") +
						"factory method '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. " +
						"Check that a method with the specified name " +
						(minNrOfArgs > 0 ? "and arguments " : "") +
						"exists and that it is " +
						(isStatic ? "static" : "non-static") + ".");
			}
			else if (void.class == factoryMethodToUse.getReturnType()) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Invalid factory method '" + mbd.getFactoryMethodName() +
						"': needs to have a non-void return type!");
			}
			else if (ambiguousFactoryMethods != null) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Ambiguous factory method matches found in bean '" + beanName + "' " +
						"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
						ambiguousFactoryMethods);
			}

			if (explicitArgs == null && argsHolderToUse != null) {
				mbd.factoryMethodToIntrospect = factoryMethodToUse;
				argsHolderToUse.storeCache(mbd, factoryMethodToUse);
			}
		}
                // 初始化bean
		bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
		return bw;
	}
Copy the code

There are too many if conditions in this method body, which can be summarized as the following steps by dismantling the main process: step1: get the name of the factory bean; Step2: Check whether the factory bean name is empty. If not, get the factory bean from the container and set the non-static method to false. Step3: If the name of the factory bean is empty, instantiate it using static methods. The rest of the above code is traversal of factory methods before initialization, sorting of factory methods, fetching parameters, and finally calling the Instantiate method for initialization. The core code for Instantiate is one sentence

return this.beanFactory.getInstantiationStrategy().instantiate( mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args); GetInstantiationStrategy () gets the instantiated strategy, in this case using the factory method to instantiate the bean into the instantiate method:  public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner, @Nullable Object factoryBean, final Method factoryMethod, Object... args) { try { if (System.getSecurityManager() ! = null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { ReflectionUtils.makeAccessible(factoryMethod); return null; }); } else { ReflectionUtils.makeAccessible(factoryMethod); } Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get(); try { currentlyInvokedFactoryMethod.set(factoryMethod); Object Result = factoryMethod.invoke(factoryBean, args); . Finally, the bean is instantiated through reflection. If the instantiation is not done through the factory method, proceed to the following code:Copy the code
// Find an instantiated bean with the @autowired annotation Constructor<? >[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors ! = null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || ! Objectutils.isempty (args)) {// If the ctors are not empty, Return autowireConstructor(beanName, MBD, ctors, args); }Copy the code
Have arguments constructor instantiation, through determineConstructorsFromBeanPostProcessors this method, is also a BeanPostProcessor interface class of applications, Will eventually be transferred to the AutowiredAnnotationBeanPostProcessor method in a class, scans in the method have annotated the constructor and then finish the assembly process. Then return the @autowired annotated constructor. Above have been given a constructor, autowireConstructor is the process to obtain parameters, the method is more complex, similar to previous instantiateUsingFactoryMethod, no longer more, take out your main core code analysis: ArgsHolder = createArgumentArray(beanName, MBD, resolvedValues, bw, paramTypes, paramNames, The createArgumentArray method gets the value of the constructor argument, enters the method, and finds the core code: Object autowiredArgument = resolveAutowiredArgument(methodParam, beanName, autowiredBeanNames, converter, fallback); The resolveAutowiredArgument method parses the value of the constructor argument and enters: / / parsing depends on the return this. The beanFactory. ResolveDependency (new DependencyDescriptor (param, true), beanName, autowiredBeanNames, typeConverter);Copy the code

Enter again:

Result = doResolveDependency(Descriptor, requestingBeanName, autowiredBeanNames, typeConverter); / / parsing candidate instanceCandidate = descriptor. ResolveCandidate (autowiredBeanName, type, this); The beanFactory.getBean(beanName) will finally feel the light of day, get the instance through the very familiar getBean, and then go to the normal getBean method, and get a conclusion from that, Fields, methods, or classes introduced with the @AutoWired annotation in their constructors are instantiated using the getBean Method to get an instance of the bean.Copy the code

InstantiateBean (beanName, MBD) This is a simple reflection instantiation. Most instantiations of classes follow this logic. Methods to enter the implementation class:

public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {override the class with CGLIB if no overrides. bd.hasMethodOverrides()) { Constructor<? > constructorToUse; synchronized (bd.constructorArgumentLock) { constructorToUse = (Constructor<? >) bd.resolvedConstructorOrFactoryMethod; if (constructorToUse == null) { final Class<? > clazz = bd.getBeanClass(); if (clazz.isInterface()) { throw new BeanInstantiationException(clazz, "Specified class is an interface"); } try { if (System.getSecurityManager() ! = null) { constructorToUse = AccessController.doPrivileged( (PrivilegedExceptionAction<Constructor<? >>) clazz::getDeclaredConstructor); } else { constructorToUse = clazz.getDeclaredConstructor(); } bd.resolvedConstructorOrFactoryMethod = constructorToUse; } catch (Throwable ex) { throw new BeanInstantiationException(clazz, "No default constructor found", ex); }}} / / reflection calls return BeanUtils. InstantiateClass (constructorToUse); } else {/ / Must generate additional ttf_subclass. / / to create additional subclasses in instantiation return after instantiateWithMethodInjection (bd, beanName, owner); }}Copy the code

When created, go back to the getSingleton method from the previous article:

If (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, () -> {try {return createBean(beanName,); mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); throw ex; }}); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }Copy the code

To review the method again:

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) { if (this.singletonsCurrentlyInDestruction) { throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction " + "(Do not request a bean from a BeanFactory in a destroy method implementation!) "); } if (logger.isDebugEnabled()) { logger.debug("Creating shared instance of singleton bean '" + beanName + "'"); } // beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } the try {/ / call createBean method to create bean singletonObject = singletonFactory. GetObject (); newSingleton = true; } catch (IllegalStateException ex) { // Has the singleton object implicitly appeared in the meantime -> // if yes, proceed with it since the exception indicates that state. singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { throw ex; } } catch (BeanCreationException ex) { if (recordSuppressedExceptions) { for (Exception suppressedException : this.suppressedExceptions) { ex.addRelatedCause(suppressedException); } } throw ex; } finally { if (recordSuppressedExceptions) { this.suppressedExceptions = null; } / / after the completion of the creation from are instantiated removes the bean bean set singletonsCurrentlyInCreation afterSingletonCreation (beanName); } if (newSingleton) {// addSingleton(beanName, singletonObject); } } return singletonObject; }}Copy the code

AddSingleton code is as follows:

protected void addSingleton(String beanName, Object singletonObject) {synchronized (enclosing singletonObjects) {/ / level cache to store the bean enclosing singletonObjects. Put (beanName, singletonObject); / / l3 cache removal bean this. SingletonFactories. Remove (beanName); / / the second level cache removal bean this. EarlySingletonObjects. Remove (beanName); // this.registeredSingletons.add(beanName); }}Copy the code

You can see that the getSingleton method does a few things altogether:

Bean created before, will create the bean is set into singletonsCurrentlyInCreation; In the process of bean creation, that is, the whole process of bean creation written in the previous article. Bean is created, the bean is removed from the collection singletonsCurrentlyInCreation created; Beans are added to level 1 cache, and beans from level 3 and level 2 caches are removed. Case 4.1 Using factory methods to create beans use the following configuration file spring.xml. The first one uses the factory-bean property without the class property behind the bean. The second way is for the bean to use the class attribute, followed by the factory-method static factory method:

<context:component-scan base-package="com.wzj"/> <bean id="factoryMethodbean" class="com.wzj.bean.FactoryMethodBean"/> <bean id="wzj" factory-bean="factoryMethodbean" factory-method="factoryMethod"/> <bean id="wzj2" Class =" com.wzj.bean.wzj "factory-method="factoryMethod"/> FactoryMethodBean  public class FactoryMethodBean { public Object factoryMethod() { return new Wzj(); } public Object factoryMethod(SC sc, CQ cq) { return new Wzj(sc,cq); }}Copy the code

The instantiated class is as follows:

public class Wzj { public static Wzj factoryMethod() { return new Wzj(); } SC sc; public Wzj() { } public Wzj(SC sc, CQ cq) { this.sc = sc; this.cq = cq; } CQ cq; } @component public class CQ implements Province{private static String flag = "CQ"; @Override public boolean support(String flag) { return CQ.flag.equalsIgnoreCase(flag); } @override public String handler() {system.out.println ("======CQ handler "); return null; } } @Component public class SC implements Province{ private static String flag = "SC"; @Override public boolean support(String flag) { return SC.flag.equalsIgnoreCase(flag); } @override public String handler() {system.out.println ("======SC handler "); return null; } } public interface Province { public boolean support(String flag); public String handler(); }Copy the code

The test class:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring.xml"})
public class TestSpring {
    @Test
    public void testCreateBeanInstance() {
        ClassPathXmlApplicationContext applicationContext =
                new ClassPathXmlApplicationContext("spring.xml");
        Wzj wzj = (Wzj) applicationContext.getBean("wzj");
        Wzj wzj2 = (Wzj) applicationContext.getBean("wzj2");
        System.out.println(wzj.getClass().getName());
        System.out.println(wzj2.getClass().getName());
    }
Copy the code

Final result:

com.wzj.bean.Wzj
com.wzj.bean.Wzj
Copy the code

4.2 Sample code for a parameterized constructor test with autowired:

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:spring.xml"}) public class TestSpring { @Test public void testCreateBeanInstance() { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml"); AutowiredConstructorBean fmc = (AutowiredConstructorBean)applicationContext.getBean("autowiredConstructorBean"); System.out.println(fmc.getClass().getName()); } Instantiate AutowiredConstructorBean: @Component Public Class AutowiredConstructorBean {@AutoWired private SC SC; @Resource private CQ cq; @Autowired public AutowiredConstructorBean(SC sc,CQ cq) { System.out.println(sc); System.out.println(cq); }}Copy the code

The result is printed as follows:

Com. WZJ. Bean AutowiredConstructorBean if add a constructor with @autowired parameters:  @Component public class AutowiredConstructorBean { @Autowired private SC sc; @Resource private CQ cq; @Autowired public AutowiredConstructorBean(SC sc,CQ cq) { System.out.println(sc); System.out.println(cq); } @Autowired(required = false) public AutowiredConstructorBean(SC sc) { System.out.println(sc); }}Copy the code

The result is an error:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'autowiredConstructorBean': Invalid autowire-marked constructor: public com.wzj.bean.AutowiredConstructorBean(com.wzj.strategy.SC). Found constructor with 'required' Autowired annotation already: public com.wzj.bean.AutowiredConstructorBean(com.wzj.strategy.SC,com.wzj.strategy.CQ) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(Autowir edAnnotationBeanPostProcessor.java:339)Copy the code

Through debugging, find the root cause of error is in the second constructor parameters, performs a AutowiredAnnotationBeanPostProcessor determineCandidateConstructors method in the following code:

if (ann ! = null) { if (requiredConstructor ! = null) { throw new BeanCreationException(beanName, "Invalid autowire-marked constructor: " + candidate + ". Found constructor with 'required' Autowired annotation already: " + requiredConstructor); }Copy the code

If you have two @autowired constructors with parameters, add required = false to both @autowired constructors. Instead, constructors are sorted in descending order by the number of arguments. Constructors with more arguments are executed first, and the following constructor is not executed.

4.3 Parameterized constructors without AutoWired

public class AutowiredConstructorBean { public AutowiredConstructorBean(SC sc,CQ cq) { System.out.println(sc); System.out.println(cq); }}Copy the code

You can also initialize it at last.

4.4 No-parameter constructor

public class AutowiredConstructorBean {
    
}
Copy the code

The above test cases can also be instantiated.

  1. conclusion

This article describes a variety of ways to instantiate beans. You can learn that Spring provides users with a variety of ways to create beans, so that you can see the flexibility of spring’s way of creating beans. When writing code, you can also consider a variety of strategies to accomplish certain functions and improve scalability and flexibility.