Spring系列之-Spring IOC容器设计:Spring实例化对象
2017-12-16 00:00
941 查看
之前我们了解到Spring在IOC依赖注入最后阶段会创建Bean的实例对象,这个对象是怎么创建的呢,什么时候该调用何种方法创建上一个环境还没有弄明白,创建对象是通过这段代码完成的。从代码注释我们可以看出这段代码的主要功能是为给定bean创建实例对象,具体的创建策略有工厂方法、构造器自动注入以及默认简单策略。
从上述代码中可以看出创建实例对象主要使用了3三种策略:
1.instantiateUsingFactoryMethod
2.autowireConstructor
3.instantiateBean
签名两种比较逻辑比较复杂,使用相对第三种比较少,暂时不深究后续有时间再研究,这里我们使用看看第三种策略是如何实现,第三种也是默认策略:
instantiate方法如下:
上述代码中如果用户没有使用replace或者lookup的配置方法配置方法直接使用JVM反射创建实例对象,否则使用Cglib创建对象。我们再次回到实例化策略
这个接口很简单,就定义了三个重载方法,其实现类在Spring4为止Juin两个类,
其中在SimpleInstantiationStrategy实现了基于JVM反射的实例化策略,如果不能满足JVM反射条件那么调用下面采用Cglig创建,该方法被子类覆盖掉了,具体实现如下:
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); }
相关文章推荐
- Spring系列之-Spring IOC容器设计:IOC容器初始化-IOC容器Resource定位
- Spring系列之-Spring IOC容器设计:IOC容器初始化-BeanDefinition解析
- spring ioc容器的学习笔记2---ioc容器系列的设计与实现
- Spring系列之-Spring IOC容器设计:依赖注入设计
- Spring系列之-Spring IOC容器设计:IOC容器初始化-Bean注册
- 动态获取Spring IOC容器实例化对象
- Spring源码解析之IoC容器系列的设计实现(IoC容器系列概况)
- 学习SSM框架笔记二:spring容器实例化对象的3种方法
- (一)IOC容器系列的设计与实现:BeanFactory和ApplicationContext
- Spring 系列: Spring 框架简介- Spring AOP 和 IOC 容器入门
- Spring源码分析(一)-Spring IoC容器的设计
- Spring IOC容器中Bean的实例化过程
- Ioc容器依赖注入-Spring 源码系列(2)
- Spring系列之IOC容器
- ioc spring 容器管理对象
- [Spring实战系列](6)配置Spring IOC容器的Bean
- Spring 系列: Spring 框架简介- Spring AOP 和 IOC 容器入门
- 【Spring】IOC容器--创建对象(六)
- 多个IoC容器适配器设计及性能测试(Castle.Windsor Autofac Spring.Core)
- spring-ioc 放开那个对象,让我(容器)来