【Spring02】Spring的基本使用

1 搭建Maven项目

2 配置

2.1 配置pom.xml

<!-- spring 依赖-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring.version}</version>
</dependency>

2.2 配置Spring配置文件

Spring的配置文件没有命名的限制,一般约定俗成的常用命名有:spring-context.xml、applicationContext.xml、beans.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
	<bean id="userService001" class="com.jackqiang.ch001hellospring.UserServiceImpl/>
</beans>
  • 需要Spring工厂生产的对象写到<bean>标签中去

  • <bean id="userService001" class="com.jackqiang.ch001hellospring.UserServiceImpl/>

    • id:自定义对象的名称,唯一值(可以省略,省略的话spring可以提供默认名称);

    • class:类的全限定名称(包名.类名),Spring会通过反射机制创建对象,注意不能是接口

3 Spring工厂编码

//1. 指定spring配置文件:从类路径(classpath)之下开始的路径
//2. 创建容器对象,ApplicationContext 表示spring容器对象, 通过ac获取某个java对象
ApplicationContext ac = new ClassPathXmlApplicationContext("beans001.xml");
//3. 从容器中获取指定名称的对象,使用getBean("id")
UserService userService001 = (UserService) ac.getBean("userService001");
//4. 调用对象的方法,接口中的方法
userService001.adduser();
  • ApplicationContext ac = ...:启动工厂;

  • serService userService001 =...:获取对象;

4 依赖与配置文件详解

4.1 依赖

2.2.1中的pom.xml文件中看似只导入了一个依赖,但是从IDEA的External Libraries中发现已经导入了6个Spring相关的依赖jar包:

查看Maven依赖的层级关系:

  • 依赖1:我们所导入的依赖;

  • 依赖2~5:依赖1所依赖的依赖;

    • 这些依赖由Maven自动导入,以后可以只写需要依赖的外层依赖;

    • Maven的传递性:当我们导入了一个依赖发现存在导入依赖所需要依赖的依赖没有导入时,Maven会自动帮我们导入;

此外,我们还可以在pom.xml中右击→Diagrams→Show Dependencies查看依赖的依赖关系:

Spring依赖之间的依赖关系如下:

4.2 schema

schema:规范,Spring配置文件中可以定义哪些标签,标签的相对位置都是存在明确规范的,我们必须严格遵守才能让Spring按照我们的意图去实现相关的功能。这些规范在Spring中的体现为.xsd文件(xml schema definition)。

例如beans的xsd文件位置:

Spring配置文件中的定级标签<beans >中包含了语义化标签的相关规范信息,通常如下:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  • xmlns=...:语义化标签所在的命名空间;

  • xmlns:xsi=...:XMLSchema-instance标签遵循Schema标签标准;

  • xsi:schemaLocation=...:xsd文件位置,用以描述标签语义、属性、取值范围等;

4.3 控制简单对象的单例、多例模式

在Spring工厂中,每一个bean的创建模式默认模式是单例模式(工厂在创建每一个bean对象时都只创建一次)。

如下:

ApplicationContext ac = new ClassPathXmlApplicationContext("beans008.xml");
User user1 = (User)ac.getBean("user");
User user2 = (User)ac.getBean("user");
User user3 = (User)ac.getBean("user");

System.out.println(user1 == user2);
System.out.println(user2 == user3);

输出结果:

true
true

虽然连续三次调用了getBean但创建的User对象都是同一个对象,如果想要创建对象是不同的对象,需要修改Spring配置文件:

<bean id="user" class="com.qianglj.test2.entity.User" scope="prototype">
  • scope="prototype":控制bean的创建模式,singleton-单例(默认),prototype-多例。

此时再执行测试程序,测试结果如下:

false
false

4.4 FactoryBean创建复杂对象

简单对象:创建过程比较简单的对象,如果需要创建对象,直接new出来即可,在Spring工厂中直接配置即可:

<bean id="address" class="com.qianglj.test2.entity.Address">
    <property name="id" value="111"/>
    <property name="city" value="xiabeize"/>
</bean>

此时Spring会通过反射中去调用class属性中配置的类的构造方法(默认是空参构造,如果使用了构造注入则会去调用指定的构造方法)。

但有些对象是属于复杂对象,不能直接通过new去创建。比如数据库连接的Connection、MyBatis的SqlSessionFactory。此时需要使用FactoryBean去创建复杂对象。

创建FactoryBean需要实现FactoryBean<T>接口:

public class MyConnectionFactoryBean implements FactoryBean<Connection> {
    @Override
    public Connection getObject() throws Exception {
        return null;
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}
  • public Connection getObject() throws Exception:完成复杂对象的创建过程;

  • public Class<?> getObjectType():复杂对象的类型;

  • public boolean isSingleton():工厂在生产复杂对象时所使用的模式是怎么样的

    • false:不是单例;

    • true:是单例。

将以上三个方法重写完毕:

public class MyConnectionFactoryBean implements FactoryBean<Connection> {
    @Override
    public Connection getObject() throws Exception {
        Class.forName("com.mysql.jdbc.Driver");
        return DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatisdb","root","1234");
    }

    @Override
    public Class<?> getObjectType() {
        return Connection.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}

配置Spring配置文件:

<bean id="connection" class="com.qianglj.test2.factorybean.MyConnectionFactoryBean"/>
  • 当class中的类是一个FactoryBean的时,获取到的对象是是其生产的对象,也即getObject的返回值;
Connection connection = (Connection)ac.getBean("connection");
  • 如果需要获取FacyoryBean本身需要在getBean方法中填入&id
MyConnectionFactoryBean bean = (MyConnectionFactoryBean) ac.getBean("&connection");

4.5 饿汉式创建优势

工厂创建之后,会将Spring配置文件中的所有对象都创建完成(饿汉式)。

这样可以提高程序运行效率,避免多次IO,减少对象创建时间。概念接近连接池,一次性创建好,使用时直接获取。

注意:只有对于单例的Bean,才会是饿汉式的创建模式。对于多例Bean,只有在使用的时候才会被创建(懒汉式)。

4.6 生命周期方法

在Spring工厂中,可以自定义初始化方法与销毁方法。

  • 自定义初始化方法:

    • 在配置文件的bean标签中添加init-method属性;

    • Spring会在创建对象之后,调用此方法;

  • 自定义销毁方法:

    • 在配置文件的bean标签中添加destroy-method属性;

    • Spring会在销毁对象之前,调用此方法;

    • 调用工厂的close对象,Spring会销毁所有已创建的单例对象;

    • Singleton对象由Spring容器销毁,Prototype对象由JVM销毁

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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="address" class="com.qianglj.test2.entity.Address" init-method="myInit" destroy-method="myDestroy">
        <property name="id" value="111"/>
        <property name="city" value="xiabeize"/>
    </bean>
</beans>

Java Bean:

public class Address {
    private Integer id;
    private String city;

    public Address() {
        System.out.println("---public Address()---");
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        System.out.println("---public void setId(Integer id)---");
        this.id = id;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        System.out.println("---public void setCity(String city)---");
        this.city = city;
    }

    public void myInit(){
        System.out.println("---public void myInit()---");
    }

    public void myDestroy(){
        System.out.println("---public void myDestroy()---");
    }
}

测试方法:

ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("beans010.xml");
ac.getBean("address");
System.out.println("======");
ac.close();

测试结果:

---public Address()---
---public void setId(Integer id)---
---public void setCity(String city)---
---public void myInit()---
======
---public void myDestroy()---

总结:Spring中bean的生命周期阶段

  • 单例bean(Singleton)

    • 随工厂启动创建

    • 构造方法

    • setter注入值

    • init初始化

    • 构建完成

    • 工厂关闭销毁

  • 多例bean(Prototype)

    • 被使用时创建

    • 构造方法

    • setter注入值

    • init初始化

    • 构建完成

    • JVM gc销毁

 

版权声明:
作者:jackqiang
链接:http://www.jackqiang.com/framework/spring/1967/use_spring/
来源:JackQiang's
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
< <上一篇
下一篇>>
文章目录
关闭
目 录