Spring IOC容器的理解

Spring是当下主流的开发框架,一个轻量级的DIAOP容器框架,核心思想是IOC和AOP,也是面试中是必问题,开发人员不可不知道,最近和很多面试官交流发现,很多人仅仅是简单知道几个概念,或者大概了解下(我也是这样,时间一长忘了),还是老话好:好记性不如烂笔头。

如何理解IOC

   我的理解是:程序之间的关系由容器管理,组件对象之间的使用关系由主动变成被动,不再直接相互依赖,也就是说组件对象的所有权交给了外部容器管理,使用时通过外部容器获取对象,控制权的转移也就是所谓反转了。目前主流的IOC实现有Spring,EJB,piconcontainer等。

 意义何在?

   在这里不能不说一种软件工程思想——DIP(依赖倒转原则)   

依赖倒置原则
A.高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。
B.抽象不应该依赖于具体实现,具体实现应该依赖于抽象。

   IOC是DIP的很好体现。解决软件各层之间的解耦,降低了业务对象替换的复杂性,更容易提高开发效率, 

  实现 

    到这里,还要理解对象是如何交由IOC容器管理呢,又如何从IOC容器中获得对象——其实就是所谓的DI和Service Locator,DI就是所谓的依赖注入,  Service Locator就是我们如何从容器中获得对象。

  DI的实现目前有三种方式:

1、使用构造函数
2、属性注入
3、接口注入

 从容器中获得对象,一般我们通过给要使用服务对象指定特定的别名通过工厂模式读取。

spring中依赖注入和Service Locator

02155453_3VzZ.jpg

使用ClassPathXmlApplicationContext、FileSystemXmlApplicationContext、XmlWebApplicationContext进行实例化,

1. ApplicationContext fileApplicationContext = new FileSystemXmlApplicationContext( "D:/workSpace/springDemo/src/resourceapplicationcontext.xml ");
2. ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext( "/applicationcontext.xml ");
3. ServletContext servletContext = request.getSession().getServletContext();
   ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext);

可以发现 spring的核心结构:

BeanFactory和BeanDefinition

无论是何种方式,使用AbstractApplicationContext#refresh())进行启动:

public void refresh() throws BeansException, IllegalStateException {
    Object var1 = this.startupShutdownMonitor;
    synchronized(this.startupShutdownMonitor) {
        this.prepareRefresh();
        ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();//加载配置并将注册bean
        this.prepareBeanFactory(beanFactory);

        try {
            this.postProcessBeanFactory(beanFactory);//为容器的某些子类指定特殊的BeanPost事件处理器
            this.invokeBeanFactoryPostProcessors(beanFactory); //调用所有注册的BeanFactoryPostProcessor的Bean 
            this.registerBeanPostProcessors(beanFactory);  //BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件 
            this.initMessageSource();//初始化信息源,和国际化相关
            this.initApplicationEventMulticaster();//初始化容器事件传播器.  
            this.onRefresh();//调用子类的某些特殊Bean初始化方法  
            this.registerListeners();//为事件传播器注册事件监听器.  
            this.finishBeanFactoryInitialization(beanFactory);//初始化所有剩余的单态Bean
            this.finishRefresh();//初始化容器的生命周期事件处理器,并发布容器的生命周期事件 
        } catch (BeansException var9) {
            if(this.logger.isWarnEnabled()) {
                this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
            }

            this.destroyBeans();//销毁bean
            this.cancelRefresh(var9);//取消启动
            throw var9;
        } finally {
            this.resetCommonCaches();//重置缓存
        }

    }

1.加载配置,DefaultBeanDefinitionDocumentReader读取xml元素委托BeanDefinitionParserDelegate解析并注册bean信息(对应上文中ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory()),并由此构建了BeanFactory

(BeanFactory构建后,在bean未在加载前,我们可通过实现BeanFactoryPostProcessor进行扩展,见后续MyBeanFactoryPostProcessor)

public class BeanDefinitionParserDelegate{
......
/**
 * Process the given bean element, parsing the bean definition
 * and registering it with the registry.
 */
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
   BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
   if (bdHolder != null) {
      bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
      try {
         // Register the final decorated instance.
         BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
      }
      catch (BeanDefinitionStoreException ex) {
         getReaderContext().error("Failed to register bean definition with name '" +
               bdHolder.getBeanName() + "'", ele, ex);
      }
      // Send registration event.
      getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
   }
}
......
}
public class BeanDefinitionReaderUtils {
......
/**
 * Register the given bean definition with the given bean factory.
 * @param definitionHolder the bean definition including name and aliases
 * @param registry the bean factory to register with
 * @throws BeanDefinitionStoreException if registration failed
 */
public static void registerBeanDefinition(
      BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
      throws BeanDefinitionStoreException {

   // Register bean definition under primary name.
   String beanName = definitionHolder.getBeanName();
   registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

   // Register aliases for bean name, if any.
   String[] aliases = definitionHolder.getAliases();
   if (aliases != null) {
      for (String aliase : aliases) {
         registry.registerAlias(beanName, aliase);
      }
   }
}

......
}

MyBeanFactoryPostProcessor

/**
 * Created by lucene on 2017/7/1.
 */
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("调用MyBeanFactoryPostProcessor的postProcessBeanFactory");
        BeanDefinition bd = beanFactory.getBeanDefinition("tester");
        System.out.println("属性值============" + bd.getPropertyValues().toString());
    }
}

2.载入Bean并初始化(文中上部分finishBeanFactoryInitialization方法),检查Bean类的限定名是否存在,如果不存在,异常抛出;

at org.springframework.util.ClassUtils.forName(ClassUtils.java:250)
    at org.springframework.beans.factory.support.AbstractBeanDefinition.resolveBeanClass(AbstractBeanDefinition.java:394)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doResolveBeanClass(AbstractBeanFactory.java:1397)
    at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1344)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineTargetType(AbstractAutowireCapableBeanFactory.java:628)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:597)
    at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1445)
    at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:975)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:752)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538)
    at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:666)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:632)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:680)
    at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:551)
    at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:492)
    at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)

对于bean的初始化进行扩展

/**
 * Created by lucene on 2017/7/1.
 */
@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInstantiation(Class<?> aClass, String s) throws BeansException {
        System.out.println("postProcessBeforeInstantiation ...." + s);
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object o, String s) throws BeansException {
        System.out.println("postProcessAfterInstantiation ...." + s);
        return false;
    }

    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues propertyValues, PropertyDescriptor[] propertyDescriptors, Object o, String s) throws BeansException {
        System.out.println("postProcessPropertyValues ...." + s);
        return propertyValues;
    }

    @Override
    public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
        System.out.println("postProcessBeforeInitialization ...." + s);
        return o;
    }

    @Override
    public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
        System.out.println("postProcessAfterInitialization ...." + s);
        return o;
    }
}
/**
 * Created by lucene on 2017/7/1.
 */
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
        System.out.println("postProcessBeforeInitialization ...." + s);
        return o;
    }

    @Override
    public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
        System.out.println("postProcessAfterInitialization ...." + s);
        return o;
    }
}

执行结果:

postProcessBeforeInstantiation ....tester
postProcessAfterInstantiation ....tester
postProcessBeforeInitialization ....tester
postProcessBeforeInitialization ....tester
postProcessAfterInitialization ....tester
postProcessAfterInitialization ....tester
postProcessBeforeInstantiation ....myInitializingBeanDisposableBean
postProcessAfterInstantiation ....myInitializingBeanDisposableBean
postProcessBeforeInitialization ....myInitializingBeanDisposableBean
postProcessBeforeInitialization ....myInitializingBeanDisposableBean

下面的实现是所有bean初始化后被执行

/**
 * Created by lucene on 2017/7/1.
 */
@Component
public class MyInitializingBean implements InitializingBean {
   
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("-----------afterPropertiesSet");
    }
}

3.获取bean(也就是在Service Locator):部分bean的初始化使用延迟初始化,也就是第一次向容器索要bean时实例化,通过工厂模式BeanFanctory去管理bean的生命周期(参考其实现类AbstractBeanFactory中createBean、doGetBean、getBean、destroyBean等方法)。

4.bean的销毁

public void destroy() {
    this.close();
}

public void close() {
    Object var1 = this.startupShutdownMonitor;
    synchronized(this.startupShutdownMonitor) {
        this.doClose();
        if(this.shutdownHook != null) {
            try {
                Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
            } catch (IllegalStateException var4) {
                ;
            }
        }

    }
}

也可自定义

/**
 * Created by lucene on 2017/7/1.
 */
@Component
public class MyInitializingDisposableBean implements DisposableBean {
    @Override
    public void destroy() throws Exception {
        System.out.println("-----------destroy");
    }
}

参考资料:

http://blog.csdn.net/hongxingxiaonan/article/details/49531891

http://uule.iteye.com/blog/2094609

转载于:https://my.oschina.net/zhaoxp/blog/913309

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值