第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生命周期????????????

 

posted on 2018-04-27 10:34  笑明子  阅读(132)  评论(0编辑  收藏  举报

导航