Spring

JavaBean

Bean:豆子,豆荚

符合一定规范的(结构雷同)简单Java对象

  1. 必须有包(package)
  2. 必须有无参数构造器
  3. 实现序列化接口
  4. 属性有get和set访问方法

符合上述规范类,创建的具体对象称为JavaBean, 也称为简单Java对象,有时候也称为POJO对象。

Spring建议,在Spring中使用JavaBean规范的对象。 但是Spring也支持不规范的Java对象。

如上规范不是语法规范,可以不严格遵守。但是大多数企业都要求执行上述规范。

Spring核心功能IOC/DI

IOC控制反转: 指对象的创建和控制权利由Spring控制,用户程序只从Spring获取使用对象。 用户程序不再负责创建管理对象。

DI依赖注入:指在需要对象时候,由当前环境创建管理对象,并且注入到使用者手中。

Spring核心功能:

  1. Spring 内部提供了一个JavaBean对象容器(集合)由于创建和管理对象。
  2. 需要提供配置文件(xml文件),Spring根据配置文件创建和管理对象。

使用Spring

  1. 导入Spring框架API

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.10.RELEASE</version>
    </dependency>
    
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    
  2. 创建一个JavaBean类

    /** 符合Java Bean 规范 */
    public class HelloWorld implements Serializable {
        private String message = "Hello World";
        public HelloWorld() {
        }
    
        public String getMessage() {
            return message;
        }
        public void setMessage(String message) {
            this.message = message;
        }
        @Override
        public String toString() {
            return "HelloWorld [message=" + message + "]";
        }
    }
    
  3. 创建一个XML文件,告诉Spring创建哪些对象

    <?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:context="http://www.springframework.org/schema/context" 
        xmlns:jdbc="http://www.springframework.org/schema/jdbc"  
        xmlns:jee="http://www.springframework.org/schema/jee" 
        xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:aop="http://www.springframework.org/schema/aop" 
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:util="http://www.springframework.org/schema/util"
        xmlns:jpa="http://www.springframework.org/schema/data/jpa"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
            http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
            http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
            http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">
    
        <!-- 利用配置文件,告诉Spring管理哪些JavaBean对象 -->
        <bean id="obj1" class="day01.HelloWorld"/>
    
    </beans>
    
  4. 启动Spring容器,Spring会根据XML文件创建对象。

    ClassPathXmlApplicationContext ctx;
    @Before //在测试案例之前执行
    public void initCtx() {
        //初始化Spring容器, 需要提供配置文件
        //配置文件默认位置为 resources
        ctx =new ClassPathXmlApplicationContext(
            "applicationContext.xml");
    }
    @After //在测试案例之后执行
    public void destroy() {
        ctx.close(); //关闭Spring容器,会销毁Bean对象
    }
    
  5. 从Spring获得创建好对象。

    @Test
    public void testHelloWorld() {
        //Spring中就已经创建了 HelloWorld对象,利用
        //ID获取Spring中创建的对象
        HelloWorld obj=(HelloWorld)ctx.getBean("obj1");
        //检查是否成功创建了对象
        System.out.println(obj); 
    }
    

Spring 容器

Spring 核心功能是管理JavaBean对象,由于其内部缓存了JavaBean对象,所以形象称为Spring为 JavaBean 容器。

  1. Spring为 JavaBean 容器。
  2. 由于Spring可以创建JavaBean对象,所以称为BeanFactory(JavaBean的工厂)
  3. 后来Spring在BeanFactory基础上扩展了接口 ApplicationContext。

Spring 容器功能使用

  1. Spring 配置文件用于声明JavaBean对象

    <bean id="obj1" class="day01.HelloWorld"/>
    
  2. Spring配置文件中 id 属性和name属性功能一样

    <!-- id 属性和 name属性作用一样 -->
    <bean name="obj2" class="day01.HelloWorld"/>
    

    常用的属性是id

  3. Spring容器提供了多个获取Bean对象的方法:

    //返回是Object类型需要进行类型转换
    Object bean = ctx.getBean("BeanID")
    
    //返回具体类型的Bean对象     
    类型 obj = ctx.getBean("BeanID", 类型)
    

案例:

<!-- 利用配置文件,告诉Spring管理哪些JavaBean对象 -->
<bean id="obj1" class="day01.HelloWorld"/>
<!-- id 属性和 name属性作用一样 -->
<bean name="obj2" class="day01.HelloWorld"/>

@Test
public void testName() {
    //利用name属性获取Spring容器中的对象
    HelloWorld obj=(HelloWorld)ctx.getBean("obj2");
    //检查是否成功创建了对象
    System.out.println(obj); 
}

@Test
public void testGetBean() {
    //Spring容器提供了多个获取Bean对象的方法:
    HelloWorld bean1 = 
            (HelloWorld)ctx.getBean("obj1");
    System.out.println(bean1);
    //返回具体类型的方法,无需类型转换(常用)
    HelloWorld bean2 = 
            ctx.getBean("obj1", HelloWorld.class);
    System.out.println(bean2); 
}

Spring 创建对象的方式

  1. 利用无参数构造器创建对象
    1. 默认情况下,Spring会自动调用(反射调用)无参数构造器创建对象。
  2. 利用静态工厂方法创建对象, Spring可以利用工厂方法来创建对象

    1. “工厂方法” 创建对象方法称为工厂方法

      //配置文件:
      <!-- Spring利用静态工厂方法创建对象 -->
      <bean id="cal1" class="java.util.Calendar"
          factory-method="getInstance"/> 
      
      //测试案例:
      @Test 
      public void testCalendar() {
          //静态方法getInstance(),来创建Calendar对象
          //创建对象的静态方法称为,静态工厂方法。
          //Calendar cal = Calendar.getInstance();
      
          //Spring支持静态工厂方法创建对象
          //Spring可以去调用静态工厂方法,将创建的对象
          //放到Spring容器管理起来,提供给外部使用。
      
          Calendar cal1 = 
                  ctx.getBean("cal1", Calendar.class);
          System.out.println(cal1); 
      }
      
  3. 利用对象工厂方法创建对象

Spring 功能强大,提供了多种创建对象的方式。

单例与多例

单例的特点:

  1. 资源占用少, 一个对象可以被复用。
  2. 并发访问时候,单例对象的属性可能出现并发访问问题。

多个实例: 1. 每个实例都有一组数据,资源占用高,可以保持多个状态 2. 如果每个线程访问一个实例,就没有线程并发安全问题

Spring默认情况下按照单例管理对象!

案例:

<!-- scope="prototype" 属性设置以后,obj3 
是多例的,每次getBean都会创建一个新对象-->
<bean id="obj3" class="day01.HelloWorld" 
    scope="prototype"/>

@Test
public void testPrototype() {
    //默认情况下Spring管理的对象是单例的
    HelloWorld obj1 = ctx.getBean("obj1",
            HelloWorld.class);
    HelloWorld obj2 = ctx.getBean("obj1",
            HelloWorld.class);
    System.out.println(obj1==obj2);
    //设置了 scope=prototype 属性返回是多例的
    HelloWorld obj3 = ctx.getBean("obj3",
            HelloWorld.class);
    HelloWorld obj4 = ctx.getBean("obj3",
            HelloWorld.class);
    System.out.println(obj3==obj4); 
}

对象的生命周期管理

Spring支持对象的生命周期管理方法。

生命周期管理方法用于初始化,或者回收资源。

  1. 默认情况下是单例对象,Spring利用属性调用初始化和销毁方法

    <!-- 测试对象生命周期管理方法 -->
    <bean id="demo" class="day01.DemoBean"
        init-method="init" destroy-method="destroy"/>
    

    关闭容器时候调用 销毁方法。 容器启动时候创建对象调用其初始化方法

  2. 多例对象时候,Spring只在创建对象时候调用init方法。 不会调用销毁方法

    <!-- 测试对象生命周期管理方法 -->
    <bean id="demo" class="day01.DemoBean"
        scopt="prototype"
        init-method="init" destroy-method="destroy"/>
    

    getBean时候,创建对象并且调用init方法 如果需要执行销毁方法,只能手动执行

案例:

public class DemoBean implements Serializable{
    private PrintWriter out;

    public void init() {
        //初始化资源
        try {
            out = new PrintWriter("demo.txt");
            System.out.println("打开文件 demo.txt"); 
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
    public void destroy() {
        //关闭资源
        out.flush();
        out.close();
        System.out.println("文件被关闭了"); 
    }
    public void print(String str) {
        out.println(str); 
    }
}

public class DemoBean2 implements Serializable{
    private PrintWriter out;

    public void init() {
        //初始化资源
        try {
            out = new PrintWriter("demo2.txt");
            System.out.println("打开文件 demo2.txt"); 
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
    public void destroy() {
        //关闭资源
        out.flush();
        out.close();
        System.out.println("文件被关闭了"); 
    }
    public void print(String str) {
        out.println(str); 
    }
}

<!-- 测试对象生命周期管理方法 -->
<bean id="demo" class="day01.DemoBean"
    init-method="init" destroy-method="destroy"/>

<!-- 测试多例对象的生命周期管理方法  
  destroy-method 写上没有意义,不会被执行-->
<bean id="demo2" class="day01.DemoBean2"
    scope="prototype"
    init-method="init"/>

@Test
public void testLifecircle() {
    //测试Spring的Bean对象的生命周期管理功能
    DemoBean bean = ctx.getBean("demo",
            DemoBean.class);
    bean.print("abc"); 
}

@Test
public void testPrototypeLifecircle() {
    //测试Spring多例Bean对象的生命周期管理功能
    DemoBean2 bean = ctx.getBean("demo2",
            DemoBean2.class);
    bean.print("abc");
    //手工调用销毁方法
    bean.destroy();
}

懒惰实例化JavaBean

lazy: 懒惰,按需实例化

lazy-init="true": 在第一次请求getBean时候实例化对象。

  1. 默认情况下Spring对于单例对象,容器启动时候立即实例化。优点是在使用对象时候,对象已经实例化,可以减少延迟,提高性能。 会占用系统资源。
  2. lazy-init="true" 属性,以后按需实例化,资源占用低,获取对象慢。
  3. 对于一定使用的对象,建议采用立即实例化规则
  4. 对于使用少的对象建议采用懒惰实例化
  5. Spring默认规则是 立即实例化

案例:

<!-- 测试对象生命周期管理方法 -->
<bean id="demo" class="day01.DemoBean"
    lazy-init="true"
    init-method="init" destroy-method="destroy"/>