IoC(控制反转)是Spring容器的内核,AOP、声明式事务等功能在此基础上开花结果。
IoC的字面意思是控制反转,是某一接口具体实现类的选择从调用类中移除,转交给第三方决定。或是让调用类对某一接口实现类的依赖关系由第三方(容器或协作类)注入。
即调用类方法需要调用接口的实现类,不是由调用类自己创建,而是通过如下方式注入:
1,属性注入,通过调用setXXX方法实现;
2,接口注入,和属性注入一样;
3、,构造函数注入,作为构造函数的入参注入;
4,通过容器完成注入;
Java基础知识
Java语音允许通过程序化的方式间接对Class的对象实例进行操作,Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获得Class的的结构信息,如构造函数,属性和方法等。
在反射操作中,有几个重要的反射操作类,分别是ClassLoader、Class、Constructor和Method,通过这些反射类可以间接调用目标Class的各项功能。
类装载器ClassLoader
类装载器就是寻找类的字节码文件,并构造出类在JVM内部表示的对象租件。步骤如下:
1,装载:查找和导入Class文件;
2,链接:执行校验、准备和解析步骤;校验是检查载入Class文件数据的正确性;准备是给内的静态变量分配存储空间;解析是将符号引用转成直接引用;
3,初始化:对象类的静态变量、静态代码块执行初始化工作。
ClassLoader负责在运行时查找和装入Class字节码文件。JVM运行时会产生三个ClassLoader:根装载器、ExtClassLoader(扩展类装载器)和AppClassLoader(系统类装载器)。
根装载器负责装载JRE的核心类库;
扩展类装载器负责装载JRE扩展目录ext中的JAR类包;
系统类装载器负责装载Classpath路径下的类包;
这三个类装载器是父子关系;
JVM装载类时使用全盘负责委托机制,
全盘负责是指当一个ClassLoader装载一个类时,该类依赖及引用类也由这个ClassLoader载入;
委托机制是指先委托父装载器寻找目标类,只有在找不到的情况下才从自己的类路径中查找并装载目标类;
ClassLoader重要方法
Class defineClass(String name, byte[] b, int off, int len)
将类文件字节码数组转换成JVM内部的java.lang.Class对象。字节数组可以从本地文件系统、远程网络获取。name为字节数组对应的全限定类名。
Class findSystemClass(String name)
从本地文件系统载入Class文件。该方法时JVM默认使用的装载机制。如果找不到Class文件,将抛出ClassNotFoundException;
Class findLoadedClass(String name)
查看ClassLoader是否已经装入某个类。返回Class对象或null;
ClassLoader getParent()
获取父装载器,如果父装载器是跟装载器,将返回null;
Java反射机制
Class反射对象描述类语义结构,可以从Class对象中获取构造函数,成员变量,方法类等元素的反射对象,并以编程方式通过这些反射对象对目标类对象进行操作。
Constructor:类的构造函数反射类;
Method:类方法的反射类;
Field:类的成员变量反射类;
在访问private、protected成员变量和方法时,必须通过setAccessible(boolean access)方法,取消Java语言检查,否则会抛出IllegalAccessException;
资源访问利器
Resource接口的主要方法:
boolean exists():资源是否存在;
boolean isOpen():资源是否打开;
URL getURL():如果底层资源可以表示成URL,该方法返回对应的URL对象;
File getFile():如果底层资源对应一个文件,该方法返回对应的文件对象;
InputStream getInputStream():返回资源对应的输入流;
Resource接口的的具体实现类:
ByteArrayResource:二进制数组表示的资源;
ClassPathResource:类路径下的资源;
FileSystemResource:文件系统资源,资源以文件系统路径的方式表示;
InputStreamResource:对应一个InputStream的资源;
ServletContextResource:为访问Web容器上下文中的资源而设计的类,负责以相对于Web根目录的路径加载资源;
UrlResource:访问任何可以通过URL表示的资源,如文件系统资源,HTTP资源,FTP资源;对于位于远程服务器(Web或FTP服务器)的文件资源,用户可以方便地通过UrlResource进行访问;
BeanFactory和ApplicationContext
BeanFactory为IoC容器,是Spring框架的基础设施,面向Spring本身;
而ApplicationContext为应用上下文,有时也叫Spring容器,面向使用Spring框架的开发者;
BeanFactory的类体系结构:
BeanFactory的主要方法时getBean(String beanName),该方法从容器中返回特定名称的Bean。
ListableBeanFactory:定义了访问容器中Bean基本信息的若干方法,如查看Bean的个数,获取某一类型Bean的配置名,查看容器中是否包含某一Bean;
HierarchicalBeanFactory:父子级联IoC容器,子容器可以通过接口方法访问父容器;
ConfigurableBeanFactory:定义了设置类装载器、属性编辑器、容器初始化后置处理方法;
AutowiredCapableBeanFactory:定义了将容器中的Bean按某种规则进行自动装配的方法;
SingletonBeanRegistry:定义了在运行容器期间向容器注册单实例Bean的方法;
BeanDefinitionRegistry:Spring配置文件中每一个<bean>节点元素在Srping容器里都通过一个BeanDefinition对象表示。而BeanDefinitionRegistry提供了向容器手工注册BeanDefinition对象的方法。
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource res = resolver.getResource("classpath:com/baobaotao/beanfactory/beans.xml");
BeanFactroy bf = new XmlBeanFactory(res);
Car car = bf.getBean("car","Car.class);
XmlBeanFactory通过Resource装载Spring配置信息并启动IoC容器,然后就可以通过BeanFactory#getBean获取Bean了。
Spring在DefaultSingletonBeanRegistry类中提供了一个用于缓存单实例Bean的缓存器,它是一个用HashMap实现的缓存器,单实例的Bean以beanName为键保存在这个HashMap中。
ApplicationContext
ApplicationContext的主要实现类时ClassPathXmlApplicationContext和FileSystemXmlApplicationContext,分别从类路径和文件系统中装配配置文件;
ApplicationEventPublisher:让容器拥有发布应用上下文事件的功能,包括容器启动事件,关闭事件等。ApplicationListener事件监听接口的Bean可以接收到容器事件,并对事件进行响应处理。在AbstractApplicationContext中,有一个ApplicationEventMulticaster,负责保存所有监听器,以便在容器产生事件时通知这些事件的监听者。
ResolverPatternResolver:装载Spring的配置文件;
ConfigurableApplicationContext扩展于ApplicationContext,新增refresh和close,让ApplicationContext具有启动,刷新和关闭应用上下文的能力;
ApplicationContext ctx = new ClassPathXmlApplicationContext("com/baobaotao/context/beans.xml");
获得了ApplicationContext实例后,就可以通过调用getBean获取Bean了。
WebApplicationContext类体系结构
专门为web应用准备的,允许从相对于Web根目录的路径中装载配置文件,完成初始化工作。从WebApplicationContext中可以获得ServletContext的引用,整个web应用上下文对象作为属性放置到ServletContext中,以便web应用可以访问Spring 上下文。
上下文启动时,WebApplicationContext以ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE为键放置在ServletContext的属性列表中。
WebApplicationContext为Bean添加了三个新的作用域:request,session和global session作用域。而在非web环境下,Bean只有singleton和prototype两种作用域。
WebApplicationContext的初始化
WebApplicationContext的初始化需要ServletContext实例,也就是说它必须拥有web容器的前提下才能完成启动工作。可以在web.xml中配置自启动的Servlet或者定义web容器监听器(ServletContextListener),借助其中之一完成启动Spring Web上下文的工作。
Spring提供用于启动WebApplicationContext的Servlet和Web容器监听器:
ContextLoaderServlet和ContextLoaderListener,两者的内部都实现了启动WebApplicationContext实例的的逻辑,只需选择其中之一在web.xml中配置就可以了。