Spring学习笔记-IoC容器

  • IoC全称为控制反转(Inverse of Control),也叫依赖注入,是spring容器的内核,AOP、事务等都依赖于此技术。IoC说白了,就是将对象与对象之间的依赖关系从代码中转移到spring的配置文件中(默认为ApplicationContext.xml 也能够自定义名字),从而由spring进行管理。这样的好处就是下降了对象与对象之间的依赖。IoC的工做原理就是利用Java的反射功能实例化对象与对象的依赖。除此以外,IoC容器还提供了对象的实例缓存、生命周期管理、对象实例代理、事件发布、资源装载等高级功能。java

  • BeanFactory接口也就是你们熟知的Bean工厂,它是spring框架最核心的接口,它提供了高级的IoC配置机制,能够管理任何不一样类型的Java对象。ApplicationContext接口是继BeanFactory接口以外,另外一个重要的接口。它的功能是创建在BeanFactory接口之上的。它除了已有的功能外,还提供国际化支持和框架事件等更多面向应用的功能。对于二者的区别用最直观最简介的方式来讲就是BeanFactory是Spring框架的内核,它是给Spring用的,而ApplicationContext接口是给使用Spring框架的开发者用的。web

  • BeanFactory是一个类工厂,但它和通常的类工厂不一样,通常的类工厂是实例化一个类或几个类,而BeanFactory是个超级工厂,能够建立管理各类类。全部被BeanFactory管理的对象在Spring中统称为Bean.下面咱们初始化BeanFactory工厂,并在工厂中获取某个对象。spring


  • spring配置文件:bean.xml缓存

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.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.xsd">
    
    <!-- 给car的全部属性赋值 -->
    <bean id="car" class="com.xiaobai.spring.mark.Car" p:brand="众泰T600S" p:color="白色" p:speed="120"></bean>

</beans>

  • 实体类Car.javasession

public class Car {
    /** 品牌 */
    private String brand;

    /** 颜色 */
    private String color;

    /** 速率 */
    private int speed;

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + '\'' +
                ", color='" + color + '\'' +
                ", speed=" + speed +
                '}';
    }
}

  • 测试类CarTest.javaapp

public class CarTest {

    /**
     * new 方式实例化car对象
     */
    @Test
    public void newCreateCar() {
        Car car = new Car();
        car.setBrand("捷豹xjl");
        car.setColor("黑色");
        car.setSpeed(200);
        System.out.println(car);
    }

    /**
     * BeanFactory 方式实例化car对象
     */
    @Test
    public void beanFactoryCreateCar() {
        ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
        Resource resource = resourcePatternResolver.getResource("classpath:xiaobai/beans.xml");
        BeanFactory beanFactory = new XmlBeanFactory(resource);
        Car car = beanFactory.getBean("car", Car.class);
        System.out.println(car);
    }
    
    /**
     * applicationContext 方式实例化car对象
     */
    @Test
    public void applicationContextCreateCar() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:xiaobai/beans.xml");
        Car car = applicationContext.getBean("car", Car.class);
        System.out.println(car);
    }
}

  • XmlBeanFactory经过Resource装载Spring配置信息并启动IoC容器,而后经过BeanFactory中的getBean()方法从IoC容器中获取Bean.根据Spring的内部机制,启动IoC容器时,并不会初始化配置文件中的Bean.当第一次调用getBean()时初始化。对于单例的Bean来讲,BeanFactory会缓存Bean实例,在第二次调用getBean()时,直接从IoC容器的缓存中获取Bean实例。接下来咱们经过下面的例子来证实BeanFactory的缓存机制。框架


  • BeanFactory的缓存测试ide

ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
Resource resource = resourcePatternResolver.getResource("classpath:xiaobai/beans.xml");
BeanFactory beanFactory = new XmlBeanFactory(resource);
Car car1 = beanFactory.getBean("car", Car.class);
Car car2 = beanFactory.getBean("car", Car.class);
System.out.println(car1);
System.out.println(car2);
  • 上述代码咱们从IoC容器中获取了两个Car,经过输出对象的内存地址信息来判断这两个car是否为同一个测试

  • 输出结果ui

com.xiaobai.spring.mark.Car@1d96f4b5
com.xiaobai.spring.mark.Car@1d96f4b5
  • 经过输出结果证实了咱们以前所说的,BeanFactory的缓存机制。但在各别状况下咱们不但愿它有缓存,咱们但愿每次访问时返回的都是一个新的对象。那怎么办呢。咱们能够经过scope属性来配置。

  • beanx.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.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.xsd">

    <!-- 给car添加scope属性并值设置为prototype -->
    <bean id="car" class="com.xiaobai.spring.mark.Car" p:brand="众泰T600S" p:color="白色" p:speed="120" scope="prototype"></bean>
</beans>
  • 输出结果

com.xiaobai.spring.mark.Car@6ecf829d
com.xiaobai.spring.mark.Car@79884a40
  • 经过结果咱们看,经过给Bean设置scope="prototype"时,IoC容器每次返回的都是一个新对象了,若是想每次返回的都是同一个对象,能够设置为scope="singleton",默认不设置scope属性时scope="singleton"


  • Spring3.0之后支持类注解的配置方式,能够经过@Configuration注解为Spring提供配置信息,Spring为配置的注解类提供了一个专门的实现类AnnotationConfigApplicationContext,下面咱们来看一下怎么来加载配置信息

  • Beans.java

@Configuration
public class Beans {
    @Bean(name = "car")
    public Car buildCar() {
        Car car = new Car();
        car.setBrand("东风标志508");
        car.setColor("白色");
        car.setSpeed(300);
        return car;
    }
}
  • 测试用例

/**
 * @Configuration 方式实例化car对象
 */
@Test
public void configurationCreateCar() {
    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Beans.class);
    Car car = applicationContext.getBean("car", Car.class);
    System.out.println(car);
}
  • 输出结果

Car{brand='东风标志508', color='白色', speed=300}

  • WebApplicationContext接口是Spring专门为Web应用准备的,它继承了ApplicationContext接口,并为Bean的scope属性增长了三个值分别是request、session、globalSession.它容许从Web根目录的路径中装载配置文件,完成初始化工做。由于它是为Web服务的,因此它必须依赖于Web容器。根据Web项目开发经验,咱们应该在web.xml配置自启动的Servlet或者Web容器监听器,来配置Web项目开发环境。Spring为这两种都提供了相应的类,来启动Spring容器。它们分别为org.springframework.web.context.ContextLoaderListener和org.springframework.web.context.ContextLoaderServlet.咱们能够根据这两种中的任何一种方式来启动WebApplicationContext。虽然两种没有什么太大的区别,均可以启动WebApplicationContext,可是只有Servlet2.3以上的版本的Web容器才支持Web容器的监听器。(包括当前版本),因此能够根据项目须要配置启动WebApplicationContext的方式。下面咱们来看一下具体的配置代码


  • web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <!--
        下面的代码是选择Spring配置文件的路径,也能够定义Spring配置文件的名字
        若是不配置Spring默认在项目根目录下查找applicationContext.xml文件
    -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <!--
            若是配置多个文件能够用逗号分隔,也能够用资源前缀的方式配置
            ? : 匹配文件名中的一个字符
            * : 匹配文件名中的任意个字符
           ** : 匹配多层路径
           classpath:com/t?st.xml 匹配com类路径下的com/tast.xml、tbst.xml 等
           classpath:com/*.xml 匹配com类路径下的全部xml文件
           classpath:com/**.xml 匹配com类路径及其子目录下的全部xml文件
        -->
        <param-value>classpath:beans.xml</param-value>
    </context-param>
    
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

</web-app>

  • 在SpringIoC容器中一个Bean对应配置文件中的一个<bean>,id为这个Bean的名称,经过容器的getBean()方法获取对应的Bean。id在IoC容器中必须是惟一的,它的命名还要知足XML对id的命名规范:必须以字母开始,后机能够是字母、数字、连字符、下划线、等。可是,在特殊状况下,咱们须要特别的名字,那id就不容许了。这时咱们能够用name属性。name属性没有字符限制,几乎可使用任何字符,并能够设置多个名字。以下所示

<bean name="#1, $2" class="com.xiaobai.spring.mark.Car" p:brand="众泰T600S" p:color="白色" p:speed="120"/>
  • Spring配置文件虽然不容许出现两个id的<bean>,但却能够出现两个name的<bean> 若是有多个name相同的<bean> 获取时,将返回最后声明的那个Bean,缘由是后面的<bean>覆盖了前面的<bean>.若是id和name两个属性都未指定,Spring自动将class作为Bean的名称。以下所示

<bean class="com.xiaobai.spring.mark.Car" p:brand="众泰T600S" p:color="白色" p:speed="120"/>
@Test
public void applicationContextCreateCar() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:xiaobai/beans.xml");
    Car car = applicationContext.getBean("com.xiaobai.spring.mark.Car", Car.class);
    System.out.println(car);
}
  • 执行结果

Car{brand='众泰T600S', color='白色', speed=120}
相关文章
相关标签/搜索