Spring-Ioc之bean注入-singleton
大家知道spring-ioc的bean注入是其核心模块。其中包括了beanDefinition的创建,bean的生命周期,特殊情况的bean-aop。最终形成的bean会有不同的scope熟悉。这里就先详细分析一下singleton-scope情况下,bean是如何通过spring的反射机制来实现注入的。
spring 5.0.8
jdk 1.8
这里会贴出进行本次分析的源码片段
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(ConfigTest.class);
ctx.refresh();
BeanTest beanTest = ctx.getBean(BeanTest.class);
String name = beanTest.getName();
System.out.println(name);
}
public class BeanTest {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Configuration
public class ConfigTest {
@Bean
public BeanTest getBeanTest(){
BeanTest beanTest = new BeanTest();
beanTest.setName("ok");
return beanTest;
}
}
了解一个最简单单例bean的实例化过程
序号 | 作用 | 类 | 方法 | 方法执行行数 |
---|---|---|---|---|
1 | AbstractApplicationContext | refresh() | 549 finishBeanFactoryInitialization(beanFactory); | |
2 | AbstractApplicationContext | finishBeanFactoryInitialization(…) | 868 beanFactory.preInstantiateSingletons() | |
3 | DefaultListableBeanFactory | preInstantiateSingletons() | 758 getBean(beanName); | |
4 | AbstractBeanFactory | doGetBean(…) | 315 sharedInstance = getSingleton(beanName, () -> { | |
5 | DefaultSingletonBeanRegistry | getSingleton(…) | 222 singletonObject = singletonFactory.getObject(); | |
6 | 这里根据不同的scope执行不同的处理代码 | AbstractBeanFactory | doGetBean(…) | 317 return createBean(beanName, mbd, args); |
7 | AbstractAutowireCapableBeanFactory | createBean(…) | 495 Object beanInstance = doCreateBean(beanName, mbdToUse, args); | |
8 | AbstractAutowireCapableBeanFactory | doCreateBean(…) | 535 instanceWrapper = createBeanInstance(beanName, mbd, args); | |
9 | AbstractAutowireCapableBeanFactory | createBeanInstance(…) | 1095 if (mbd.getFactoryMethodName() != null) { | |
10 | AbstractAutowireCapableBeanFactory | instantiateUsingFactoryMethod(…) | 1247 return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs); | |
11 | 通过参数匹配找到并执行工厂方法 | ConstructorResolver | instantiateUsingFactoryMethod(…) | 581 beanInstance = this.beanFactory.getInstantiationStrategy().instantiate |
12 | 这个方法是创建bean对象,最终执行反射的地方 | SimpleInstantiationStrategy | instantiate |
SimpleInstantiationStrategy.instantiate
public class SimpleInstantiationStrategy implements InstantiationStrategy {
...
//这个方法是创建bean对象,最终执行反射的地方。
//部分参数说明
//beanName getBeanTest
//factoryBean {ConfigTest$$EnhancerBySpringCGLIB$$b5d90a6e}注意这里,所有@Configuration类在启动时都使用CGLIB进行子类化
//factoryMethod public com.kaxudodo.demo.BeanTest com.kaxudodo.demo.ConfigTest.getBeanTest()
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
@Nullable Object factoryBean, final Method factoryMethod, @Nullable 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 {
//将方法对象放入当前 ThreadLocal currentlyInvokedFactoryMethod
currentlyInvokedFactoryMethod.set(factoryMethod);
//通过反射生成对象bean
Object result = factoryMethod.invoke(factoryBean, args);
if (result == null) {
result = new NullBean();
}
return result;
}
finally {
if (priorInvokedFactoryMethod != null) {
currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
}
else {
//从currentlyInvokedFactoryMethod中删除方法对象
currentlyInvokedFactoryMethod.remove();
}
}
}
catch (IllegalArgumentException ex) {
throw new BeanInstantiationException(factoryMethod,
"Illegal arguments to factory method '" + factoryMethod.getName() + "'; " +
"args: " + StringUtils.arrayToCommaDelimitedString(args), ex);
}
catch (IllegalAccessException ex) {
throw new BeanInstantiationException(factoryMethod,
"Cannot access factory method '" + factoryMethod.getName() + "'; is it public?", ex);
}
catch (InvocationTargetException ex) {
String msg = "Factory method '" + factoryMethod.getName() + "' threw exception";
if (bd.getFactoryBeanName() != null && owner instanceof ConfigurableBeanFactory &&
((ConfigurableBeanFactory) owner).isCurrentlyInCreation(bd.getFactoryBeanName())) {
msg = "Circular reference involving containing bean '" + bd.getFactoryBeanName() + "' - consider " +
"declaring the factory method as static for independence from its containing instance. " + msg;
}
throw new BeanInstantiationException(factoryMethod, msg, ex.getTargetException());
}
}
ConstructorResolver.instantiateUsingFactoryMethod
//代理解决构造函数和工厂方法。通过参数匹配执行构造函数解析。
class ConstructorResolver {
...
//使用命名的工厂方法来声明bean。
public BeanWrapper instantiateUsingFactoryMethod(
final String beanName, final RootBeanDefinition mbd, @Nullable final Object[] explicitArgs) {
//BeanWrapperImpl是个bean包装对象。默认的BeanWrapper实现应该足以满足所有典型用例。 为了提升效率,缓存内省结果。这里不展开,关于缓存内省结果可以计划另开一篇博文
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
Object factoryBean;
Class<?> factoryClass;
boolean isStatic;
String factoryBeanName = mbd.getFactoryBeanName();
//这里判断是否是静态工厂方法,如果存在工厂beanName则不是
//这里的factoryBeanName值为"configTest"
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;
}
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;
}
//无论是静态或者非静态,上述代码都将找出工厂方法对于的工厂类(factoryClass)
Method factoryMethodToUse = null;
ArgumentsHolder argsHolderToUse = null;
Object[] argsToUse = null;
//这里判断工厂方法是否有传入参数,本例是null
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
else {
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
//从mbd里面找是否有已经处理过的构造或者工厂方法,本例这里同样为空
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);
}
}
//到这里factoryMethodToUse还是为null,会进入这个if块,获取最终的factoryMethodToUse
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还是被spring代理的代理工厂类 class ConfigTest$$EnhancerBySpringCGLIB$$cc75d322
factoryClass = ClassUtils.getUserClass(factoryClass);
//执行以后通过ClassUtils.getUserClass找到了代理类的父类 class ConfigTest
//这一段代码获取候选工厂方法,并进行排序(sortFactoryMethods),首选公共方法,使用最多参数的“贪婪”方法。
Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
List<Method> candidateSet = new ArrayList<>();
for (Method candidate : rawCandidates) {
if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
candidateSet.add(candidate);
}
}
Method[] candidates = candidateSet.toArray(new Method[0]);
AutowireUtils.sortFactoryMethods(candidates);
ConstructorArgumentValues resolvedValues = null;
boolean autowiring = (mbd.getResolvedAutowireMode() == RootBeanDefinition.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.
//当mdb需要构造参数,而在编码过程中没有传入参数的时候,进行处理
//本例中mdb不需要构造参数,不会进入此逻辑
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) {
Class<?>[] paramTypes = candidate.getParameterTypes();
if (paramTypes.length >= minNrOfArgs) {
ArgumentsHolder argsHolder;
//这段逻辑是为了得到argsHolder,分为有传入参数和无传入参数
if (explicitArgs != null){
// Explicit arguments given -> arguments length must match exactly.
if (paramTypes.length != explicitArgs.length) {
continue;
}
//在确保传入参数和工厂方法参数数量一致的情况下得到argsHolder
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);
}
//参数的类型转换或自动装配发生在createArgumentArray方法中,这里就不展开了
argsHolder = createArgumentArray(
beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring);
}
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;
}
}
//这一段代码通过比较argsHolder中的参数和候选方法中的参数来得到差异权重
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this factory method if it represents the closest match.
//这里注意minTypeDiffWeight是在for循环外部定义,一旦差异权重比最小差异权重小,则更新相关属性
//包括:将使用的工厂方法,argsHolderToUse ,argsToUse ,minTypeDiffWeight
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) {
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) {
argsHolderToUse.storeCache(mbd, factoryMethodToUse);
}
}
try {
Object beanInstance;
if (System.getSecurityManager() != null) {
final Object fb = factoryBean;
final Method factoryMethod = factoryMethodToUse;
final Object[] args = argsToUse;
beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
beanFactory.getInstantiationStrategy().instantiate(mbd, beanName, beanFactory, fb, factoryMethod, args),
beanFactory.getAccessControlContext());
}
//这里就进入上一个源代码的方法了,进行bean的创建
else {
beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, factoryBean, factoryMethodToUse, argsToUse);
}
bw.setBeanInstance(beanInstance);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean instantiation via factory method failed", ex);
}
}