第4章 IoC容器


1、IoC(控制反转)是Spring容器的核心,AOP、声明式事务等都基于IoC。
2、IoC:某一接口的实现类不由调用类来决定,而是交给第三方来决定。控制权翻转到第三方。
3、由于IoC这个词不够见名知意,后来软件界泰斗级别的人物Martin Fowler提出了ID(依赖注入)来代替。
4、IoC类型:
IoC可以划分为三种:构造函数注入、属性注入、接口注入。Spring支持构造函数注入和属性注入。
构造函数注入:
将接口实现类通过调用类的构造函数的参数传入到调用类中。(调用类不用关心谁才是实现类,只需要关心实现类会在构造函数中传入)
属性注入:
由于实现类不一定就必须在初始化是出现。因此可以使用属性注入。即通过属性的SetXxx方法注入到类中。
接口注入:
将调用方法中所有解决依赖的方法抽取到一个接口中。然后调用方法实现这个接口即可。
5、通过容器完成依赖关系的注入
程序的依赖关系交给容器完成,程序开发人员专注于开发更有意义的业务逻辑。这是我们期望的。
Spring容器,通过使用java或者xml文件来描述依赖关系,并自动完成初始化和依赖注入的工作。
下面是演员饰演角色的案例:
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans">
xmlns:xsi="http://www.w4.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<bean id = "geli" class = "xxx.yyy.刘德华">
<bean id = "moAttack" class = "com.smart.ioc.MoAttack" p:geli-ref="geli" /> <!--通过geli-ref建立依赖关系-->
</beans>
使用 new XmlBeanFactory("beans.xml")等方法即可启动容器。容器启动后根据描述信息自动实例化Bean并完成依赖关系的装配。这个神奇的功能是通过java反射实现的。
6、类装载的工作机制
类装载器通过字节码文件在jvm中创建表示类的组件。类装载器将类装入jvm中需要以下几个步骤。
1:装载:查找和导入Class文件
2:链接:执行校验(校验文件的真确性)、准备(给静态成员分配空间)和解析(将符号引用转换为直接引用)等。
3:初始化:对类的静态变量,静态代码块进行初始化工作。
7、资源抽象接口
Spring提供了一个Resource的接口,为应用提供了更强的底层资源访问能力,拥有对不同资源的访问能力,在Spring中它起到了很大作用(加载各种资源)。
Resource的主要方法:
Boolean exists(): 资源是否存在
Boolean isOpen(): 资源手否打开
URL getURL() throws IOException: 如果底层资源可以表示成URL,那么返回URL。
File getFile() throws IOException: 如果底层资源对应于一个File,返回对应的File对象。
8、BeanFactory和ApplicationContext
BeanFactory是Spring最为核心的接口。ApplicationContext建立在BeanFactory之上,提供了更多面向应用的功能。
BeanFactory我们一般称为IoC容器,ApplicationContext称之为上下文。为了方便有时候也将ApplicationContext称之为容器。
BeanFactory:
Spring框架的基础设施,面向Spring本身。
ApplicationContext:
面向Spring框架的使用者,几乎所有的应用场合都使用ApplicationContext而不使用BeanFactory。
9、BeanFactory:
正如其名,BeanFactory是一个工厂,但是和传统的工厂有所不同,它可以创建和管理各种java对象。Spring将这些对象称之为Bean。
但是javaBean是一个规范(有无参构造、不依赖特定容器等。)但是SpringBean比较宽泛,被容器管理的都叫做Bean。
Spring为BeanFactory提供了多种实现。目前建议使用的是:XmlBeanDefinitionReader和DefaultListableBeanFactory。
通过BeanFactory的继承体系可以清晰的看出BeanFactory提供了那些功能。
初始化BeanFactory
下面使用Spring配置文件描述Car,然后使用BeanFactory装载配置文件。启动SpringIoC容器。
beans.xml配置文件
<bean id = "car1" class = "com.smart.Car">
p:brand="红旗"
p:color="黑色"
p:maxSpeed="200"
</bean>
下面通过XMLBeanDefinitionReader和DefaultListableBeanFactory实现启动SpringIoC容器。
public class BeanFactoryTest{
@Test
public void getBean() throws Throwable{
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource res = resolver.getResource("classpath:com/smart/beanFactory/beans.xml"); //获取配置文件资源
System.out.println(res.getURL());

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XMLBeanDefinitionReader reader = new XMLBeanDefinitionReader(factory);
reader.loadBeanDefinitions(res); //XMLBeanDefinitionReader通过Resource装载配置信息、启动IoC容器。
//启动IoC容器后并不会立刻实例化bean,而是在使用时才创建。
//对于单例的Bean来说,bean会被缓存起来,下次使用直接调用。
Car car = factory.getBean("car" , Car.class);
car.introduce();
}
}
10、ApplicationContext介绍
ApplicationContext是在BeanFactory的基础上派生出来的。实现了很多功能。
ApplicationContext的主要实现类是:ClassPathXMLApplicationContext(默认从类路径加载配置文件)和FileSystemXMLPathApplicationContext(默认从文件系统中加载配置)
从ApplicationContext的继承体系可以看到,它继承了BeanFactory的实现类并扩展了其功能。
ConfigurableApplicationContext扩展了ApplicationContext它结合了生命周期类,让ApplicationContext具有了如下方法
refresh(),close()让ApplicationContext具有了启动、刷新、关闭的能力。
在上下文关闭的情况下使用refresh()可启动上下文
在启动上下文的情况下使用refresh()可清除缓存并重写转载配置信息。
调用close()方法会关闭上下文。
初始化ApplicationContext
如果配置文件在类路径下:可以使用ClassPathCmlApplicationContext实现类
ApplicationContext ctx = new ClassPathCmlApplicationContext("com/smart/context/beans.xml");
//对于ClassPathCmlApplicationContext来说"com/smart/context/beans.xml"等同于:"classpath:com/smart/context/beans.xml"
如果配置文件放在文件系统下可以优先考虑:FileSystemXmlApplicationContext类
ApplicationContext ctx = new FileSystemXmlApplicationContext("com/smart/context/beans.xml")
//对于FileSystemXmlApplicationContext来说"com/smart/context/beans.xml"等同于:"file:com/smart/context/beans.xml"
如果要指定一组配置文件可以使用以下形式:
new new FileSystemXmlApplicationContext(new String[]{"com/smart/context/beans.xml","config.xml","config2.xml"})
11、javaConfig
Spring提供了使用java配置Bean的方法
可以使用@Configuration注解标识一个POJO类为Spring提供Bean的描述。
例如:
@Configuration
public class Beans{
@Bean{name = "car"}
public Car buildCar(){
Car car = new Car(); 这种方法容易控制初始化过程。
car.xxx();car.yyy();
return car;
}
}
Spring为基于注解的配置类提供了专门的ApplicationContext:AnnotationConfigApplicationContext。
启动容器:
public class AnnotationApplicationContextTest{
@Test
public void getBean(){
//通过一个javaConfig类创建上下文
ApplicationContext ctx = new AnnotationConfigApplicationContext(Beans.class);
//获取Bean
Car car = new Car("car" , Car.class);
}
}
12、Spring4.0还支持Groovy DSL 进行Bean定义的配置。使用Groovy容易实现比较复杂的Bean初始化配置。
13、WebApplicationContext类体系结构
WebApplicationContext是Spring专门为Web准备的上下文。它允许从web根路径中装配文件完成初始化。
为了使web中的servletContext对象可以使用Spring的上下文,WebApplication作为属性在ServletContext中。
Spring专门提供了一个WebApplicationUtils的类,使用该类的getWebApplicationContext(ServletContext sc)方法可以从ServletContext中取到WebApplicationContext
WebApplicationContext也可以返回ServletContext的引用。从而实现web应用上下文和web容器的互相访问。
14、ConfigurableWebApplicationContext
ConfigurableWebApplicationContext扩展了WebApplicationContext。允许通过配置的方式实例化WebApplicationContext。同时提供了两个有用的方法:
1:setServletContext(ServletContext servletContext)
为Spring设置web上下文,以便二者结合。
2:setConfigLocations(String[] configLocations)
设置Spring配置文件地址,一般情况下Spring配置文件地址是相对于Web根目录的地址。例如:“/WEB-INF/smart-service.xml”
但使用setConfigLocation也可以指定资源类型前缀,如:"classpath:smart-service.xml"
15、WebApplicationContext初始化
由于WebApplicationContext的创建需要ServletContext实例。所以和ApplicationContext和BeanFactory有所区别。
可以通过在web.xml中配置自启动的servlet或者定义Web容器监听器。
下面是Spring提供的用于启动WebApplicationContext的Servlet和Web容器监听器,实现二者其一,并在web.xml中配置即可。
1:org.springframework.web.context.ContextLoaderListener。
下面是使用ContextLoaderListener启动WebApplicationContext的配置
<!--指定配置文件-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/smart-dao.xml,/WEB-INF/smart-service.xml
</param-value>
</context-param>
<!--声明Web容器监听器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
2:org.springframework.web.context.ContextLoaderServlet。
如果web容器不支持容器监听器(一些第版本的web容器就不支持)。可以使用ContextLoaderServlet
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/smart-dao.xml,/WEB-INF/smart-service.xml</param-value>
</context-param>
<!--声明自动servlet-->
<servlet>
<servlet-name>springContextLoaderServlet</servlet-name>
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
<!--启动顺序-->
<load-on-startup>1</load-on-startup>
</servlet>
由于WebApplicationContext需要使用日志,可以将log4J的配置文件放在WEB-INF/classes下,这样log4J就可以顺利启动了。
如果log4J的配置文件放在了别的地方,需要用户在web.xml中配置log4J的配置位置。Spring为Log4J提供了启动类。具体看书。
16、bean生命周期????????????









猜你喜欢

转载自www.cnblogs.com/Xmingzi/p/8961195.html