【spring源码系列】之【Bean的实例化】

目录

 


人生需要探索的热情、坚持的勇气以及热爱生活热爱自己的力量。

1. Bean的实例化

上一篇讲述了bean的生命周期,其中第一步就涉及到了bean的实例化,本文重点分析bean实例化,先进入源码中的AbstractAutowireCapableBeanFactory类中的createBeanInstance方法。

2. 流程概览

上述图描述了bean的实例化过程中的主要步骤:

  1. 如果存在 Supplier 回调,则调用 obtainFromSupplier() 进行初始化;
  2. 如果存在工厂方法,则使用工厂方法进行初始化;
  3. 如果构造函数参数不为空,则先获取autowired注解的构造函数,再获取构造函数里面的参数,参数是引用类型的话,再次循环调用容器去获取,最后通过反射完成实例化;
  4. 如果构造函数无参,则使用默认无参构造函数实例化;
  5. 最后将bean添加到一级缓存,并清除二级三级缓存里的bean。

3. 源码分析

3.1 createBeanInstance概览

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(); // 使用Supplier接口获取 if (instanceSupplier != null) { return obtainFromSupplier(instanceSupplier, beanName); } // 使用FactoryMethod方法实例化 if (mbd.getFactoryMethodName() != 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? // 构造函数有参autowired修饰 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); } // No special handling: simply use no-arg constructor. // 默认实例化 return instantiateBean(beanName, mbd); }

3.1 使用Supplier接口

Supplier<?> instanceSupplier = mbd.getInstanceSupplier(); // 使用Supplier接口获取 if (instanceSupplier != null) { return obtainFromSupplier(instanceSupplier, beanName); }

进入obtainFromSupplier方法

protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) { Object instance; String outerBean = this.currentlyCreatedBean.get(); this.currentlyCreatedBean.set(beanName); try { // 从instanceSupplier获取 instance = instanceSupplier.get(); } finally { if (outerBean != null) { this.currentlyCreatedBean.set(outerBean); } else { this.currentlyCreatedBean.remove(); } } if (instance == null) { instance = new NullBean(); } // 包装成BeanWrapper BeanWrapper bw = new BeanWrapperImpl(instance); // 初始化BeanWrapper initBeanWrapper(bw); return bw; }

上述源码显示从从instanceSupplier获取,而instanceSupplier是一个函数式接口:

@FunctionalInterface public interface Supplier<T> { /** * Gets a result. * * @return a result */ T get(); }

那在何时对该instanceSupplier进行设值的呢?不妨来看一下RootBeanDefinition:

protected BeanWrapper instantiateUsingFactoryMethod( String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) { return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs); }

由此可见,在初始化BeanDefinition的时候,就已经将instanceSupplier设值, 随后从instanceSupplier.get()获取,最后包装成BeanWrapper对象后,对其初始化。

3.2 使用FactoryMethod方法实例化

如果工厂方法不为空,则使用工厂方法实例化:

// 使用FactoryMethod方法实例化 if (mbd.getFactoryMethodName() != null) { return instantiateUsingFactoryMethod(beanName, mbd, args); }

下面进入instantiateUsingFactoryMethod方法:

protected BeanWrapper instantiateUsingFactoryMethod( String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) { return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs); }

先创建一个ConstructorResolver对象,然后调用其instantiateUsingFactoryMethod方法,该方法细节很多,看如下主要步骤:

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

这个方法体太多if条件,通过拆解主要流程可以归纳为以下步骤:
step1:获取工厂bean的名字;
step2:判断工厂bean名字是否为空,如果不为空,从容器中获取工厂bean,并将非静态方法设为false;
step3:如果工厂bean的名字为空,则使用静态方法实例化。
上述其他代码都是初始化前工厂方法的遍历,工厂方法的排序、以及参数的获取,最终再调用instantiate方法完成初始化;而instantiate的核心代码就一句话

return this.beanFactory.getInstantiationStrategy().instantiate( mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args);

getInstantiationStrategy()获取实例化的策略,这里是使用工厂方法来实例化bean,进入instantiate方法:

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

最终是通过反射完成bean的实例化。

3.3 有参构造函数实例化

如果没有通过工厂方法完成实例化,那么继续玩下走如下代码:

// 寻找实例化的bean中有@Autowired注解的构造函数 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { // 如果ctors不为空,就说明构造函数中有@Autowired注解 return autowireConstructor(beanName, mbd, ctors, args); }

有参构造函数的实例化过程,通过determineConstructorsFromBeanPostProcessors这个方法完成,同时也是BeanPostProcessor接口类的应用,最终会调到 AutowiredAnnotationBeanPostProcessor类的方法,在方法中会扫描有注解的构造函数然后完成装配过程。然后把有@Autowired 注解的构造函数返回。

上面已经拿到了构造函数,autowireConstructor就是获取参数的过程,其方法比较复杂,跟之前的instantiateUsingFactoryMethod类似,不再细究,把主要核心代码拿出来分析:

// 获取构造函数参数的值 argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,

createArgumentArray方法,获取构造函数参数的值,进入方法,找到核心代码:

// 解析所有构造函数的参数值 Object autowiredArgument = resolveAutowiredArgument(methodParam, beanName, autowiredBeanNames, converter, fallback);

resolveAutowiredArgument方法解析构造函数参数的值,再进入:

// 解析依赖 return this.beanFactory.resolveDependency(new DependencyDescriptor(param, true), beanName, autowiredBeanNames, typeConverter);

再次进入:

// 执行解析依赖 result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
// 解析candidate instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
beanFactory.getBean(beanName)

最终会感觉眼前一亮,通过非常熟悉的getBean获取实例,然后会走到普通情况下的getBean方法,通过上面得到一个结论,不管是 Field、Method、还是构造函数中有@Autowired 注解引入的类,都是通过getBean方法进行实例化获取bean的实例的。

3.4 无参构造函数实例化

无参构造函数的实例化过程 instantiateBean(beanName, mbd)这就是简单的反射实例化。大部分类的实例化都会走这个逻辑。进入实现类的方法:

public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) { // Don't override the class with CGLIB if no overrides. // 如果没有方法覆盖 if (!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); } } } // 反射调用 return BeanUtils.instantiateClass(constructorToUse); } else { // Must generate CGLIB subclass. // 创建cglib子类后在实例化 return instantiateWithMethodInjection(bd, beanName, owner); } }

3.5 bean实例化后的收尾工作

当创建完后,回到上一篇讲的getSingleton方法:

// 创建bean实例 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); }

再来回顾一下该方法:

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 + "'"); } // bean单例创建前 beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } try { // 调用createBean方法创建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; } // 创建完成后要从正在实例化的bean集合singletonsCurrentlyInCreation中删除该bean afterSingletonCreation(beanName); } if (newSingleton) { // bean加入缓存 addSingleton(beanName, singletonObject); } } return singletonObject; } }

以及addSingleton相关代码如下:

protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { // 一级缓存存放bean this.singletonObjects.put(beanName, singletonObject); // 三级缓存移除bean this.singletonFactories.remove(beanName); // 二级缓存移除bean this.earlySingletonObjects.remove(beanName); // this.registeredSingletons.add(beanName); } }

可以看出getSingleton方法总共做了如下几件事:

  1. bean创建前,将正在创建的bean放入singletonsCurrentlyInCreation集合;
  2. bean创建过程中,就是上一篇写的bean的创建整个过程,本篇只是涉及建实例这一个环节;
  3. bean创建后,从集合singletonsCurrentlyInCreation中移除正在创建的bean;
  4. bean加入一级缓存,同时移除三级缓存与二级缓存中的bean。

4. 案例

4.1 使用工厂方法创建bean

使用如下配置文件spring.xml,第一种是使用factory-bean属性,bean后面不带class属性;第二种是bean使用class属性,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); } }

实例化类如下:

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

依赖的属性值分别代表四川、重庆,实现了Province接口:

@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处理类处理"); 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处理类处理"); return null; } }
public interface Province { public boolean support(String flag); public String handler(); }

测试类:

@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()); }

最后结果:

com.wzj.bean.Wzj com.wzj.bean.Wzj

4.2 带有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()); }

实例化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); } }

结果会打印如下:

com.wzj.bean.AutowiredConstructorBean

如果再加一个带@Autowired参数的构造函数:

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

结果就会报错:

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(AutowiredAnnotationBeanPostProcessor.java:339)

通过调试,发现报错的根源是在第二次拿构造函数的参数时,执行了AutowiredAnnotationBeanPostProcessor中determineCandidateConstructors方法的如下代码:

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

提示已经有required修饰的构造函数存在,解决上述问题,如果有两个@Autowired注解的有参构造函数,需要将两个构造函数@Autowired都加上required = false)。只不过构造函数会根据参数个数的多少降序排序,参数多的构造函数会优先执行,后面的那个构造函数不会被执行。

4.3 不带有autowired的有参构造函数

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

最后也能完成初始化。

4.4 无参构造函数

public class AutowiredConstructorBean { }

通过上面测试案例最后也能完成实例化。

5. 总结

本篇讲述了bean实例化的多种方式,可以学到spring为用户提供多种创建方式,从而看出spring创建bean方式的灵活性,在我们写代码时候,也可以考虑多种策略,来完成某种功能,提高可扩展性与灵活性。

posted @ 2021-07-05 10:37  dreamw  阅读(174)  评论(0编辑  收藏  举报