人生需要探索的热情、坚持的勇气以及热爱生活热爱自己的力量。
1. Bean的实例化
上一篇讲述了bean的生命周期,其中第一步就涉及到了bean的实例化,本文重点分析bean实例化,先进入源码中的AbstractAutowireCapableBeanFactory
类中的createBeanInstance
方法。
2. 流程概览
上述图描述了bean的实例化过程中的主要步骤:
- 如果存在
Supplier
回调,则调用obtainFromSupplier()
进行初始化; - 如果存在工厂方法,则使用工厂方法进行初始化;
- 如果构造函数参数不为空,则先获取
autowired
注解的构造函数,再获取构造函数里面的参数,参数是引用类型的话,再次循环调用容器去获取,最后通过反射完成实例化; - 如果构造函数无参,则使用默认无参构造函数实例化;
- 最后将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方法总共做了如下几件事:
- bean创建前,将正在创建的bean放入singletonsCurrentlyInCreation集合;
- bean创建过程中,就是上一篇写的bean的创建整个过程,本篇只是涉及建实例这一个环节;
- bean创建后,从集合singletonsCurrentlyInCreation中移除正在创建的bean;
- 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方式的灵活性,在我们写代码时候,也可以考虑多种策略,来完成某种功能,提高可扩展性与灵活性。