Spring framework version:5.1.4 RELEASE
Spring Container在启动时, 会将配置中的bean进行实例化. 具体进行实例化操作的地方就是AbstractAutowireCapableBeanFactory.createBeanInstance().
AbtractAutowireCapableBeanFacotry.createInstance()
在createInstance()根据不同的bean-definition采取不同的实例化策略:
- facotry-method(工厂方法实例化)
- constructor autowiring(构造函数注入实例化)
- simple instantiate(简单实例化,默认无参构造函数实例化)
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());
}
// ?? jdk 1.8提供的函数编程Supplier来进行实例化
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 1. 使用工厂方法进行实例化
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);
}
}
// 2. 使用构造函数自动注入方式实例化
// Candidate constructors for autowiring?
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);
}
// 3. 简单实例化,使用默认构造函数
// No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);
}
通过阅读上面的源码,可以了解到spring提供了3种实例化的策略. 下面就讨论3种实例化策略具体怎么实现的.(ps:jdk 1.8提供的函数式编程Supplier方式进行的实例化放在文章最后讨论)
BeanWrapper??
AbstractAutowireCapableBeanFactory和实例化策略InstantiateStrategy的类图:
可以看到AbstractAutowireCapableBeanFactory中3中实例化策略最终都是交给instantiateStrategy:CglibSubclassingInstantiateStrategy类实现的.
ConstructResolver只是完成了一些辅助工作.
InstantiateStrategy Bean实例化策略
instantiate no-args constrcutor流程图
instantiate via given constrcutor流程图
instantiate via given factory-method流程图
@Override
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);
// factoryMethod.invoke反射得到实例化bean
Object result = factoryMethod.invoke(factoryBean, args);
if (result == null) {
result = new NullBean();
}
return result;
}
finally {
if (priorInvokedFactoryMethod != null) {
currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
}
else {
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());
}
}
Object result = factoryMethod.invoke(factoryBean, args);反射调用工厂方法获取bean实例. 如果工厂方法是要实例化bean中的静态工厂方法, 此时factoryBean=null,也可以反射调用类的静态方法. 在ConstructResolver中也有相关的设值.
Object factoryBean;
Class<?> factoryClass;
boolean isStatic;
String factoryBeanName = mbd.getFactoryBeanName();
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
factoryBean = null;
factoryClass = mbd.getBeanClass();
isStatic = true;
}
Supplier实例化策略
在AbstractAutowireCapableBeanFactory中采用Supplier<?>来进行实例化的代码:
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// resovle bean class ...
// strategy: supplier<?>
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// strategy: factory-method...
// strategy: autowire-constructor...
// strategy: simple instante: default no-args constructor
}
Supplier<?>是jdk1.8中添加的函数式编程新特性, 在学习之前最好对jdk 1.8函数式编程有一定的了解.
Supplier<?>在spring创建实例和factory-method实现的效果差不多,只是另外一种编程方式的实现.
AbstractBeanDefinition.setInstanceSupplier()
/**
* Specify a callback for creating an instance of the bean,
* as an alternative to a declaratively specified factory method.
* <p>If such a callback is set, it will override any other constructor
* or factory method metadata. However, bean property population and
* potential annotation-driven injection will still apply as usual.
* @since 5.0
* @see #setConstructorArgumentValues(ConstructorArgumentValues)
* @see #setPropertyValues(MutablePropertyValues)
*/
public void setInstanceSupplier(@Nullable Supplier<?> instanceSupplier) {
this.instanceSupplier = instanceSupplier;
}
在官方源码注释中也说道Supplier<?>方式是对XML-Config <bean id='' factory-method='' class=''/>的一种替代方案
Specify a callback for creating an instance of the bean, as an alternative to a declaratively specified factory method.
Supplier<?>注册bean使用方式:
Example:
//using registerBean(beanClass, beanSupplier, customizers)
public static void main(String[] args) {
GenericApplicationContext gac = new GenericApplicationContext();
gac.registerBean(LogService.class, LogService.LogServiceImpl::new,
Customizers::lazy, Customizers::defaultInitMethod);
gac.refresh();
System.out.println("context refreshed");
LogService ls = gac.getBean(LogService.class);
ls.log("msg from main method");
gac.close();
}
LogService.LogServiceImpl::new 就是一个Supplier
Spring在创建bean的时候如何保证beanClass已经被加载进来
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);
// actual create bean instance
....
}
resolveBeanClass(mbd,beanName)确保了在创建bean实例的时候,bean对应的Class已经加载进来. 在resolveBeanClass(mbd,beanName)中针对不同的情况使用了Class.forName(className)和classLoader.loadClass(className)来对beanClass进行加载.
Question: Class.forName(className)和classLoader.loadClass(className)的类加载有什么不同?
A: 两者都能完成对类Class的加载. Class.forName(className)加载进来的Class是已经完成初始化的; 而classLoaader.loadClass(className)则是没有进行初始化的.
例如: 数据库驱动中的初始化代码
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
public Driver() throws SQLException {
}
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
}
通过Class.forName('com.mysql.jdbc.Driver') 加载数据库驱动类,会完成com.mysql.jdbc.Driver中的static静态初始化代码块. 这样我们才能后面使用DriverManager.getDriver(url)来获取到对应的数据库驱动进行连接.
使用classLoader.loadClass(className)仅加载Class对象到内存, 不负责初始化. 所以在数据库驱动类的加载中不适合使用classLoader.loadClass(className)来加载数据库驱动类.