您的位置:首页 > 编程语言 > Java开发

Spring系列之-Spring IOC容器设计:Spring实例化对象

2017-12-16 00:00 941 查看
之前我们了解到Spring在IOC依赖注入最后阶段会创建Bean的实例对象,这个对象是怎么创建的呢,什么时候该调用何种方法创建上一个环境还没有弄明白,创建对象是通过这段代码完成的。从代码注释我们可以看出这段代码的主要功能是为给定bean创建实例对象,具体的创建策略有工厂方法、构造器自动注入以及默认简单策略。

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
// Make sure bean class is actually resolved at this point.
//获取bean的Class对象
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());
}
//如果工厂方法不为null则使用工厂方法(xml中配置了factory-method)策略创建实例,
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);
}
}

// Need to determine the constructor...
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
return autowireConstructor(beanName, mbd, ctors, args);
}

// 如果既不存在工厂方法、又不存在有参构造函数那么使用无参构造函数进行初始化。
return instantiateBean(beanName, mbd);
}

从上述代码中可以看出创建实例对象主要使用了3三种策略:

1.instantiateUsingFactoryMethod

2.autowireConstructor

3.instantiateBean

签名两种比较逻辑比较复杂,使用相对第三种比较少,暂时不深究后续有时间再研究,这里我们使用看看第三种策略是如何实现,第三种也是默认策略:

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;
final BeanFactory parent = this;
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
return getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
}, getAccessControlContext());
}
else {
//调用实例化策略实例化对象
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
//分装对象
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}

instantiate方法如下:

@Override
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
//不需要动态改变方法默认使用JVM反射,否则使用Cglib
if (bd.getMethodOverrides().isEmpty()) {
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(new PrivilegedExceptionAction<Constructor<?>>() {
@Override
public Constructor<?> run() throws Exception {
return clazz.getDeclaredConstructor((Class[]) null);
}
});
}
else {
constructorToUse =	clazz.getDeclaredConstructor((Class[]) null);
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(bd, beanName, owner);
}
}

上述代码中如果用户没有使用replace或者lookup的配置方法配置方法直接使用JVM反射创建实例对象,否则使用Cglib创建对象。我们再次回到实例化策略

InstantiationStrategy

这个接口很简单,就定义了三个重载方法,其实现类在Spring4为止Juin两个类,



其中在SimpleInstantiationStrategy实现了基于JVM反射的实例化策略,如果不能满足JVM反射条件那么调用下面采用Cglig创建,该方法被子类覆盖掉了,具体实现如下:

protected Object instantiateWithMethodInjection(RootBeanDefinition bd, String beanName, BeanFactory owner) {
throw new UnsupportedOperationException("Method Injection not supported in SimpleInstantiationStrategy");
}

@Override
protected Object instantiateWithMethodInjection(RootBeanDefinition bd, String beanName, BeanFactory owner) {
return instantiateWithMethodInjection(bd, beanName, owner, null);
}

@Override
protected Object instantiateWithMethodInjection(RootBeanDefinition bd, String beanName, BeanFactory owner,
Constructor<?> ctor, Object... args) {

// Must generate CGLIB subclass...
return new CglibSubclassCreator(bd, owner).instantiate(ctor, args);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息