Spring是当下主流的开发框架,一个轻量级的DI和AOP容器框架,核心思想是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
使用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