IOC容器浅浅浅浅析

控制反转是spring提供的最基础的功能.   它被视为一种与Gof所不同的设计模式.   

简单的说, 当我们在一个类A 中无法做全部的事情, 需要使用另一个类B 时,需要对B有依赖的关系. 这时候我们会通过new对象的方式获取B的对象. 或者使用工厂的方式获取B对象.  这种方式都是正常的控制关系. 

而控制反转 改变的就是这个对应关系. 我们通过spring的BeanFactory获取B对象, spring自动给B对象赋值. 我们在我们的类中就失去了对B的控制关系.  这个控制关系转移到了spring中.  通过注解/配置文件的方式,由springframework 来管理这一关系. 

 

这一波操作起到的效果是解耦.  之前被调用的类变成了Spring提供的用户自定义的服务, 放在了自定义的容器里面. 变成了应用的基础服务. 调用者A不知道B什么时候被创建,什么时候被赋值. 他只需要告诉BeanFactory我需要B对象.  剩下的spring会自己处理.

 ----------------------------------------------------------------------

那么第一个问题来了:  为什么由spring管理依赖关系会降低应用的耦合性呢? 他降低耦合性体现在了哪里? 

个人觉得,  我们在应用中存在的大量的服务都是属于不变的操作, 它们的创建,赋值都是一些基础的服务. 对于应用来说,维护他的关系是一件吃力不讨好的事情, 把他当做一个基础服务的模块之后即不需要关系他的生命周期,又可以在外部维护它的具体关系. 本身就是降低耦合性的最大特征

------------------------------------------------------------------------

 

那么问题又来了:  spring是如何维护我们提供的这些自定义服务的呢?

一切从spring的BeanFactory接口开始.  


package org.springframework.beans.factory;

import org.springframework.beans.BeansException;
import org.springframework.core.ResolvableType;

public interface BeanFactory {
    //转义符“&”用来获取FactoryBean自己
    String FACTORY_BEAN_PREFIX = "&";
    //根据bean的名字进行获取bean的实例
    Object getBean(String var1) throws BeansException;

    <T> T getBean(String var1, Class<T> var2) throws BeansException;

    <T> T getBean(Class<T> var1) throws BeansException;

    Object getBean(String var1, Object... var2) throws BeansException;

    <T> T getBean(Class<T> var1, Object... var2) throws BeansException;

    boolean containsBean(String var1);

    boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;

    boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;

    Class<?> getType(String var1) throws NoSuchBeanDefinitionException;

    String[] getAliases(String var1);
}

它的子类实现如 XmlBeanFactory AplicationContext等实现了获取对象的基本方法. 

 

首先是Ioc容器的初始化.  它分为三个过程:  Resource定位, BeanDefinition的载入, 向Ioc容器注册BeanDefinition

资源定位: 文件系统通过FileSystemResource,类路径中的Bean通过ClassPathResource进行载入. 这是一个寻找数据的过程. 

载入: 把定义好的Bean转换为IoC容器内部的数据结构.  其实就是解析Xml文件,转为Document树,然后将配置文件中静态的配置信息存放在固定的位置. 

注册: 这一步中,把BeanDefinition存储到HashMap中, 这样IoC容器中就拥有了方便管理的Bean对象对应的数据结构 可以在beanDefinitionMap中被检索使用. 

容器的作用就是对这些信息进行维护和处理. 这些数据是建立依赖反转关系的基础........

 

接着就是我们通常会用到的依赖注入. 

一般的依赖注入是我们第一次向容器索要对象是进行的. 如果想改变这一过程,需要在配置中指明 lazy-init属性,让容器进行预实例化.   (这个默认就是容器预实例化.  如果想要提高项目启动速度,可以将部分不需要预实例化的Bean 的对应值设置为true. )

 

预实例化就是在启动项目时候完成一次依赖注入. 

 

getBean是依赖注入的起点, creatBean则是依赖注入的实现. 

 protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
        if(this.logger.isDebugEnabled()) {
            this.logger.debug("Creating instance of bean '" + beanName + "'");
        }

        RootBeanDefinition mbdToUse = mbd;
        Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
        if(resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }

        try {
            mbdToUse.prepareMethodOverrides();
        } catch (BeanDefinitionValidationException var7) {
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", var7);
        }

        Object beanInstance;
        try {
            beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
            if(beanInstance != null) {
                return beanInstance;
            }
        } catch (Throwable var8) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var8);
        }

        beanInstance = this.doCreateBean(beanName, mbdToUse, args);
        if(this.logger.isDebugEnabled()) {
            this.logger.debug("Finished creating instance of bean '" + beanName + "'");
        }

        return beanInstance;
    }

创建Bean时, 会获取实例化bean需要的参数,创建bean对象并赋值。

 

创建Bean对象具体实现方法内, 首先判断是否存在可以实例化的Bean对象。 然后通过ClassLoader进行加载。 如果加载不到则判断有没有对应的工厂类。  通过工厂类的方法进行加载。  接着判断是否可以走构造方法创建, 

204915_amDd_3674060.png

    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
        Class<?> beanClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
        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());
        } else if(mbd.getFactoryMethodName() != null) {
            return this.instantiateUsingFactoryMethod(beanName, mbd, args);
        } else {
            boolean resolved = false;
            boolean autowireNecessary = false;
            if(args == null) {
                Object var7 = mbd.constructorArgumentLock;
                synchronized(mbd.constructorArgumentLock) {
                    if(mbd.resolvedConstructorOrFactoryMethod != null) {
                        resolved = true;
                        autowireNecessary = mbd.constructorArgumentsResolved;
                    }
                }
            }

            if(resolved) {
                return autowireNecessary?this.autowireConstructor(beanName, mbd, (Constructor[])null, (Object[])null):this.instantiateBean(beanName, mbd);
            } else {
                Constructor<?>[] ctors = this.determineConstructorsFromBeanPostProcessors(beanClass, beanName);
                return ctors == null && mbd.getResolvedAutowireMode() != 3 && !mbd.hasConstructorArgumentValues() && ObjectUtils.isEmpty(args)?this.instantiateBean(beanName, mbd):this.autowireConstructor(beanName, mbd, ctors, args);
            }
        }
    }

 

instantiateBean 方法在最后判断是否执行。 

    protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
        try {
            Object beanInstance;
            if(System.getSecurityManager() != null) {
                beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
                    public Object run() {
                        return AbstractAutowireCapableBeanFactory.this.getInstantiationStrategy().instantiate(mbd, beanName, AbstractAutowireCapableBeanFactory.this);
                    }
                }, this.getAccessControlContext());
            } else {
                beanInstance = this.getInstantiationStrategy().instantiate(mbd, beanName, this);
            }

            BeanWrapper bw = new BeanWrapperImpl(beanInstance);
            this.initBeanWrapper(bw);
            return bw;
        } catch (Throwable var6) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", var6);
        }
    }

 

System.getSecurityManager 安全管理器是一个单独的对象,在java虚拟机中,它在访问控制-对于外部资源的访问控制-起到中枢作用  使用native方法doPrivileged 进行授权操作。 否则直接通过java构造器 反射进行实例化并赋值。 

 

在spring3.x中使用了BeanUtils和CGLIB动态字节码方式创建实例。  由于对于 feild method constructer 的invoke方法被优化很多次,CGLIB被完爆。 在加之spring4.x仅能运行在默认增强反射的jdk1.7中, 在spring4.3.9中我们仅仅能看到使用 BeanUtils携带的 构造器反射一种实现方式。 

 

 

 

看源码全靠猜。。 鬼知道对不对!  

 

 

 

转载于:https://my.oschina.net/u/3674060/blog/1538506

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值