• 第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生命周期????????????
  • 相关阅读:
    使用 typeof bar === "object" 来确定 bar 是否是对象的潜在陷阱是什么?
    null和undefined的区别?
    JS中 [] == ![]结果为true,而 {} == !{}却为false
    kaptcha验证码使用
    Java Web应用中获取用户请求相关信息,如:IP地址、操作系统、浏览器等信息
    springboot注解
    算法思想
    数据结构
    springboot设置接口超时
    mybatis动态sql
  • 原文地址:https://www.cnblogs.com/Xmingzi/p/8961195.html
Copyright © 2020-2023  润新知