Spring 学习(二)

Java Bean 规范

JavaBean:符合一定规范的Java对象,JavaBean规范不是语法规范,违反不会有编译错误。

  1. 需要定义包package。
  2. 有无参数构造器
  3. 需要实现序列化接口
  4. 包含使用 getXxx setXxx 声明的“Bean属性” xxx
    1. Bean属性(Bean Property)就是指 setXxx getXxx 方法
    2. 对象属性(Object Field)是指对象的实例变量。

例子:

class Person{
    private String name="范传奇"; //实例变量,对象属性

    String getName(){    //Bean属性  name
        return name;
    }
    void setName(String name){    //Bean属性  name
        this.name = name;
    }
    String getLastName(){        //Bean属性  lastName
        return name.substring(0,1);
    }
}

 

例子:

Spring Hello World!

  1. 导入Spring IOC 组件包
  2. 创建被Spring IOC管理的对象组件 类
  3. 创建配置文件:通知Spring管理哪个对象组件
  4. 创建应用程序
    1. 创建Spring容器,读取Spring配置文件
    2. 从Spring容器中获取,被Spring管理的对象(控制反转)
    3. 调用对象的方法(验证)输出HelloWorld!

 

1.使用Junit测试更方便 导入Spring和JUnit包:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>4.3.9.RELEASE</version>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>

2.创建 Java Bean类:

public class Demo {
    public void test() {
        System.out.println("Hello World!");
    }
}

3.编写配置文件 applicationContext.xml, 保存到resource文件夹

<?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">

    <!-- 
        class 用于通知Spring,Spring会读取class属性的值
        在Spring内部利用反射创建对象
        id用于标识识别对象,id属性不能重复!
     -->
    <bean id="demo" class="day01.Demo"></bean>

</beans>

4.编写测试类:

public class TestCase {
    ClassPathXmlApplicationContext ctx; //实例变量
    @Before // init() 会在测试案例之前执行
    //一般用于初始化测试案例的环境,如:初始化Spring容器
    public void init() {
        ctx=new ClassPathXmlApplicationContext( "applicationContext.xml");
    }
    @After // destroy 销毁,在测试案例执行以后执行
    //用于回收系统资源。
    public void destroy() {
        ctx.close();
    }
    @Test
    public void testDemo() {
        /**
         * Spring Hello World!
         */
        Demo demo = (Demo)ctx.getBean("demo");
        demo.test();
    }

}

Spring支持对象别名

在Spring配置文件中可以为Java Bean对象定义别名,别名与ID功能一样:

<!-- alias: 别名,曾用名 -->
<alias name="demo" alias="demo1"/>

测试

@Test
public void testAlias(){
    /*
     * 测试 在Spring中为 Java Bean对象声明别名
     */
    Demo demo = (Demo) ctx.getBean("demo1");
    demo.test();
}

 

bean标签的id和name属性功能一样

配置文件:

<!-- bean 标签上的 id 属性和name属性功能一样
  大多数使用 id 属性!id属性值不能重复 -->
<bean name="demo2" class="day01.Demo"></bean> 

重载的getBean方法

Spring 容器提供了 重载的getBean方法, 可以自动完成类型转换,不用写强制转型

@Test
public void testGetBean() {
    /*
     * Spring 容器提供了 重载的getBean方法,
     * 可以自动完成类型转换,不用写强制转型
     */
    // 第一个参数是 Bean 的ID,第二个参数Bean对象的类型
    Demo demo = ctx.getBean("demo", Demo.class);
    demo.test();
}

Spring Bean对象作用域(Scope)

  1. Spring 容器默认情况下按照“单例”管理对象。
    1. 单例:在软件中对象是唯一的一个实例现象
    2. 多次调用getBean获得的是同一个的对象的引用
  2. Spring使用bean标签的scope属性可以指定多例
  3. Spring默认情况下单例方式可以提高性能。

单例案例:

@Test
public void testSingleton() {
    /*
     * 默认情况下 Spring 按照单例规则管理对象
     * 使用同一个ID多次调用 getBean获得的引用是
     * 同一个对象的引用。
     */
    Demo d1 = ctx.getBean("demo", Demo.class);
    Demo d2 = ctx.getBean("demo", Demo.class);
    System.out.println(d1==d2); //true
}

 

多例案例配置:

<!-- scope 属性声明“原型prototype”创建多个实例
每次调用getBean时候都会创建一个新实例 -->
<bean id="myBean" class="day01.Demo"  scope="prototype"/>

测试:

@Test
public void testPrototype() {
    /*
     * 使用scope="prototype"创建多个对象实例
     * 每次调用getBean方法都会创建一个对象实例
     */
    Demo d1 = ctx.getBean("myBean", Demo.class);
    Demo d2 = ctx.getBean("myBean", Demo.class);
    System.out.println(d1==d2);
}

 

bean 对象生命周期管理方法

  1. init-method 用于设定 初始化方法,创建对象以后立即执行
  2. destroy-method 用于设定 销毁方法,关闭容器销毁对象时候执行
    1. 仅对单例对象有效,多例对象上设置无效。

单例对象生命周期管理案例:

  1. 创建Bean类型

Spring 学习(二)

 

 

 配置:

Spring 学习(二)

 

 

 测试:

Spring 学习(二)

 

 

 

 

自动注入

  1. autowire="byName" 根据名字自动注入:根据对象的Bean属性名查找匹配Bean的ID,如果名字一致, 则自动注入Bean属性。 如果注入的对象类型不兼容,则失败。
  2. autowire="byType" 根据类型自动注入:根据对象的Bean属性类型查找匹配Bean的类型,如果类型兼容, 则自动注入Bean属性。 如果注入的对象类型不唯一,则出错误。

配置:

<!-- 测试按名字自动注入 -->
<bean id="worker" class="day02.Worker" autowire="byName"></bean>
<bean id="tool" class="day02.Saw"></bean>

 

Bean属性参数注入

Spring 支持各种类型参数注入:

  1. 编写测试类

public class DemoBean {
    private int num;
    private double price;
    private boolean test;
    private String name;

    //List集合
    private List<String> city;
    //数组
    private String[] arr;
    //Set集合
    private Set<String> names;
    //对象集合
    private List<Tool> tools;

    /*
     * Spring 支持基本类型Bean属性注入 
     */
    public int getNum() {
        return num;
    }
    public void setNum(int num) {
        this.num = num;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
    public boolean isTest() {
        return test;
    }
    public void setTest(boolean test) {
        this.test = test;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public List<String> getCity() {
        return city;
    }
    public void setCity(List<String> city) {
        this.city = city;
    }
    public String[] getArr() {
        return arr;
    }
    public void setArr(String[] arr) {
        this.arr = arr;
    }
    public Set<String> getNames() {
        return names;
    }
    public void setNames(Set<String> names) {
        this.names = names;
    }
    public List<Tool> getTools() {
        return tools;
    }
    public void setTools(List<Tool> tools) {
        this.tools = tools;
    }
    @Override
    public String toString() {
        return "DemoBean [num=" + num + ", price=" + price + ", test=" + test + ", name=" + name + ", city=" + city
                + ", arr=" + Arrays.toString(arr) + ", names=" + names + ", tools=" + tools + "]";
    }

}

配置:

<!-- Spring 可以为Bean对象注入各种类型的"Bean属性" -->
<bean id="demoBean" class="day02.DemoBean">
    <!-- 使用vaule属性注入基本值(基本类型和字符串) -->
    <property name="num" value="58"/>
    <property name="price" value="88.8"/>
    <property name="name" value="Tom"/>
    <property name="test" value="true"/>

    <!-- 使用 array 子元素注入数组 -->
    <property name="arr">
        <array>
            <value>黄</value>
            <value>品</value>
            <value>青</value>
            <value>黑</value>
        </array>
    </property>
    <!-- list子元素注入集合 -->
    <property name="city">
        <list>
            <value>魔都</value>
            <value>帝都</value>
            <null></null> <!-- 注入 null 值 -->
        </list>
    </property>
    <!-- set子元素注入set集合 -->
    <property name="names">
        <set>
            <value>熊大</value>
            <value>熊二</value>
        </set>
    </property>
    <!-- 注入对象集合, list 元素和 bean 元素配合实现-->
    <property name="tools">
        <list>
            <bean class="day02.Axe"></bean>
            <bean class="day02.Saw"></bean>
            <!-- ref 用于引用Spring容器中的Bean对象 -->
            <ref bean="axe"/>
        </list>
    </property>
</bean>

测试:

@Test
public void testBeanProperty() {
    /*
     *  Spring 可以为Bean对象注入各种类型的"Bean属性" 
     *  DI 功能很强大!
     */
    DemoBean bean=ctx.getBean("demoBean", DemoBean.class);
    System.out.println(bean); 
}

 

利用Spring 管理数据库连接池

利用Spring的ICO和DI功能,管理DBCP数据库连接池。

  1. 导入数据库连接池和数据库驱动

配置:

<!-- Bean属性注入的用途:利用Spring管理数据库连接池 -->
<bean id="dataSource"
    class="org.apache.commons.dbcp.BasicDataSource">
    <!-- 利用DI功能注入String类型的基本值 -->
    <property name="driverClassName" 
        value="com.mysql.jdbc.Driver"/>
    <property name="url" 
        value="jdbc:mysql:///db1"/>
    <property name="username" value="root"/>
    <property name="password" value="root"/>
    <property name="maxActive" value="10"/>
</bean>

测试:

@Test
public void testDataSource() throws Exception{
    /*
     * Bean属性注入的用途:利用Spring管理数据库连接池
     */
    // DBCP 的 BasicDataSource 类实现了 
    // javax.sql.DataSource 接口,所以可以利用DataSource
    // 接口定义变量引用 BasicDataSource实例
    DataSource ds = ctx.getBean("dataSource",
            DataSource.class);
    Connection conn = ds.getConnection();
    String sql = "select 'Hello World!' as s";
    Statement st = conn.createStatement();
    ResultSet rs = st.executeQuery(sql);
    while(rs.next()) {
        System.out.println(rs.getString("s"));
    }
    conn.close();
}

Spring 读取 Properties

Spring支持读取Properties文件功能,用于获取配置文件参数。

案例:

  1. 编写配置文件 resource/jdbc.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=UTF-8
username=root
password=root
maxActive=10

使用spring 读取:

<!-- 读取 Properties -->
<util:properties id="jdbc"  location="classpath:jdbc.properties"/>

测试:

@Test
public void testProperties() {
    /*
     * 读取 Properties 文件
     */
    Properties cfg = ctx.getBean("jdbc",Properties.class);
    System.out.println(cfg);
}

 

Spring 表达式

可以读取 Java Bean 属性,读取数组、List、Map、Properties等数据

假设 Bean 的 ID 是 demoBean 和 jdbc

  1. 读取"Bean属性"
    1. #{demoBean.num}
    2. #{demoBean.name}
    3. #{demoBean['price']}
  2. 读取数组
    1. #{demoBean.arr[0]}
    2. #{demoBean.city[1]}
  3. 读取Map、Properties
    1. #{jdbc.driver}
    2. #{jdbc['url']}

案例: 利用Spring表达式读取属性,注入到 testBean 中

编写 TestBean

public class TestBean {

    int value;
    String str;
    String driver;
    String city;

    public int getValue() {
        return value;
    }
    public void setValue(int value) {
        this.value = value;
    }
    public String getStr() {
        return str;
    }
    public void setStr(String str) {
        this.str = str;
    }
    public String getDriver() {
        return driver;
    }
    public void setDriver(String driver) {
        this.driver = driver;
    }
    public String getCity() {
        return city;
    }
    public void setCity(String city) {
        this.city = city;
    }
    @Override
    public String toString() {
        return "TestBean [value=" + value + ", str=" + str + ", driver=" + driver + ", city=" + city + "]";
    }


}

配置

<!-- 利用Spring表达式读取信息,注入到TestBean -->
<bean id="testBean" class="day02.TestBean">
    <property name="value" value="#{demoBean.num}"/>
    <property name="city"  value="#{demoBean.city[0]}"></property>
    <property name="str" value="#{demoBean.arr[0]}"/>
    <property name="driver" value="#{jdbc.driver}"/>
</bean> 

测试:

@Test
public void testSpringEx() {
    /*
     * 测试:使用Spring表达式读取Bean属性
     */
    TestBean bean = ctx.getBean("testBean",TestBean.class);
    System.out.println(bean); 
}

使用Spring 表达式配置 DBCP 连接池

  1. 配置

<!-- 使用 Properties 文件 + Spring表达式配置
DataSource 连接池 -->
<bean id="ds" 
    class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="#{jdbc.driver}"/>    
    <property name="url" value="#{jdbc.url}"/>
    <property name="username" value="#{jdbc.username}"/>
    <property name="password" value="#{jdbc.password}"/>
    <property name="maxActive" value="#{jdbc.maxActive}"/>
</bean>

测试:

@Test
public void testDS() throws Exception{
    /*
     * Spring 表达式配置JDBC连接池
     */
    DataSource ds = ctx.getBean("ds", DataSource.class);
    Connection conn = ds.getConnection();
    String sql = "select 'Hello World!' as s";
    Statement st = conn.createStatement();
    ResultSet rs = st.executeQuery(sql);
    while(rs.next()) {
        System.out.println(rs.getString("s"));
    }
    conn.close();
}

 

基于注解扫描的IOC组件管理

Spring 提供了基于注解扫描的组件管理,支持Java EE标准注解。

  1. 导入包:

Spring 学习(二)

 

 

 2.配置XML:

<!-- 开启注解扫描功能,扫描day02包以及子包 -->
<context:component-scan base-package="day02"/>

3.编写Bean组件类

@Component
public class HelloBean {
    @Override
    public String toString() {
        return "Hello World!";
    }
}

4.测试:

@Test
public void testHelloBean() {
    /*
     * 测试注解组件扫描方式创建Bean对象
     */
    HelloBean bean = ctx.getBean("helloBean", HelloBean.class);
    System.out.println(bean); 
}

Spring 支持多种注解创建Bean组件

这些注解功能基本相同:

@Component
@Named
@Service
@Repository
@Controller

案例 @Repository 声明组件:

  1. 定义Bean组件

@Repository
public class MyBean {
    @Override
    public String toString() {
        return "myBean";
    }
}

2.测试

@Test
public void testRepository() {
    /*
     * 测试注解 Repository
     */
    MyBean bean=ctx.getBean("myBean", MyBean.class);
    System.out.println(bean); 
}

注解可以自定义Bean ID

案例:

  1. 编写Bean




上一篇:解决spring boot中普通类中使用service为null 的方法


下一篇:spring基于xml的IOC环境搭建和入门