Java EE3-我独自整合(第二章:Spring IoC 入门案例)

关联完整版:Spring IoC 入门案例(完整)


loC入门案例

创建空项目

空项目中创建模块


在项目中引入需要的依赖

复制代码
<dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
      <version>1.2</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>5.2.13.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>5.2.13.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-expression</artifactId>
      <version>5.2.13.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.13.RELEASE</version>
    </dependency>
  </dependencies>

创建Spring核心配置文件所在目录


applicationContext.xml文件复制到resources包下

复制代码
<?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:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>

创建包和类


java 复制代码
package com.tianshi.domain;

import java.util.Objects;

public class Student {

    private Integer id;     //身份唯一标识
    private String name;    //姓名

    public Integer id() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String name() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return Objects.equals(id, student.id) && Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name);
    }
}

在test包下创建StudentTest测试类





java 复制代码
package com.tianshi.test;

import com.tianshi.domain.Student;

public class StudentTest {
    public static void main(String[] args) {
        //耦合方式管理Student对象
        Student student = new Student();
        student.setId(1);
        student.setName("张三");
        System.out.println(student);
    }
}

测试结果如下

在applicationContext.xml核心配置文件中管理Student对象

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:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans.xsd">

        <!--Spring框架的核心配置文件-->
        <!--一个bean标签就是一个domain对象,让Spring框架帮忙创建管理这个对象
            id      唯一标识
            class   类型的具体名称,必须写包名.类名
        -->
        <bean id="1" class="com.tianshi.domain.Student"/>

</beans>

在StudentTest测试类中通过Spring容器来创建Student的对象

java 复制代码
package com.tianshi.test;

import com.tianshi.domain.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class StudentTest {
    public static void main(String[] args) {
//        //耦合方式管理Student对象
//        Student student = new Student();
//        student.setId(1);
//        student.setName("张三");
//        System.out.println(student);

        //通过Spring容器创建Student的对象
        //创建Spring容器,创建的容器指定读取配置文件为类型的构造参数
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
        Student student=(Student)applicationContext.getBean("student");
        student.setId(2);
        student.setName("李四");
        System.out.println(student);

    }
}

Bean实例化的两种方式

通过构造方法实例化

  • 通过构造方法进行实例化,默认使用无参构造,这种方式和以前new的方式是等效的
  • 上面的Spring项目其实就是这种,只需要在XML中通过的class属性指定类的全限定路径,然后就可以实例化对象

通过工厂实例化

静态工厂&实例工厂实例化

  • 通过静态工厂、实例工厂和工厂Bean(FactoryBean)进行实例化,这种方式完全是根据设计模式中工厂模式的思想而研发出的
  • Spring考虑到如果需要频繁实例化某个类的对象,工厂模式无疑是一个好选择



静态代码块初始化的饿汉单例
java 复制代码
package com.tianshi.factory;


import com.tianshi.domain.Student;

/**
 * 静态工厂:生产对象的方法(工厂方法)是静态方法
 * 要生产的产品对象可以生产多个还是只能生产一个,假设只生产一个
 * 在极端情况下,如果只能生产一个对象的时候,是否会生产多个
 */
public class StudentStaticFactory {
    /**
     * 静态代码块实现饿汉单例
     * 生产唯一的产品
     */
    private static Student student;

    /**
     * 静态代码块,仅在类加载时运行唯一一次,保证产品对象的唯一
     * 注意:静态属性的定义+初始化和静态代码块优先级一致
     * 要注意前后顺序
     */
    static{
        student = new Student();
    }

    /**
     * 静态工厂方法
     * @return 工厂方法生产的对象
     */
    public static Student getStudent(){
        return student;
    }
}
静态常量(final)直接初始化的饿汉单例(推荐)
java 复制代码
package com.tianshi.factory;

import com.tianshi.beans.Book;

/**
 * Book静态工厂。
 * 静态工厂:生产对象的方法(工厂方法)是静态方法。
 * 要生产的产品对象,可以生产多个还是只能生产一个? 假设只生产一个产品
 * 在极端情况下,如果只能生产一个对象的时候,是否会生产多个?
 */
public class BookStaticFactory {
    /**
     * 生产的唯一产品
     */
    private static Book book;

    /**
     * 静态代码块,仅在类加载时运行唯一一次。保证产品对象的唯一。
     * 注意:静态属性的定义+初始化,在代码优先级上与静态初始化代码块一致。
     * 要注意代码定义的前后顺序。
     */
    static {
        book = new Book();
    }
    /**
     * 静态工厂方法
     * @return 工厂方法生产的对象。
     */
    public static Book newBook(){
        System.out.println("静态工厂方法运行,创建Book对象");
        return book;
        // return new Book(); // 生产多个。
    }
}
裸new多例静态
java 复制代码
package com.tianshi.factory;


import com.tianshi.domain.Student;

/**
 * 静态工厂:生产对象的方法(工厂方法)是静态方法
 * 要生产的产品对象可以生产多个还是只能生产一个,假设只生产一个
 * 在极端情况下,如果只能生产一个对象的时候,是否会生产多个
 */
public class StudentStaticFactory {
    /**
     * 静态代码块实现饿汉单例
     * 生产唯一的产品
     */
//    private static Student student;

//    /**
//     * 静态代码块,仅在类加载时运行唯一一次,保证产品对象的唯一
//     * 注意:静态属性的定义+初始化和静态代码块优先级一致
//     * 要注意前后顺序
//     */
//    static{
//        student = new Student();
//    }

    /**
     * 静态工厂方法
     * @return 工厂方法生产的对象
     */
    public static Student getStudent(){
        return new Student();//生产多个
    }

//    /**
//     * 静态常量(final)直接初始化的饿汉单例,编译限制,禁止给引用对象重新赋值
//     * 生产唯一的产品
//     */
//    private final static Student student=new Student();
//
//    /**
//     * 静态工厂方法
//     * @return 工厂方法产生的对象
//     */
//    public static Student getStudent(){
//        return student;
//    }
}
初始化多例静态(推荐)
java 复制代码
package com.tianshi.factory;


import com.tianshi.domain.Student;

/**
 * 静态工厂:生产对象的方法(工厂方法)是静态方法
 * 要生产的产品对象可以生产多个还是只能生产一个,假设只生产一个
 * 在极端情况下,如果只能生产一个对象的时候,是否会生产多个
 */
public class StudentStaticFactory {
//    /**
//     * 静态代码块实现饿汉单例
//     * 生产唯一的产品
//     */
//    private static Student student;
//
//    /**
//     * 静态代码块,仅在类加载时运行唯一一次,保证产品对象的唯一
//     * 注意:静态属性的定义+初始化和静态代码块优先级一致
//     * 要注意前后顺序
//     */
//    static{
//        student = new Student();
//    }
//
//    /**
//     * 静态工厂方法
//     * @return 工厂方法生产的对象
//     */
//    public static Student getStudent(){
//        return new Student();//生产多个
//    }

//    /**
//     * 静态常量(final)直接初始化的饿汉单例,编译限制,禁止给引用对象重新赋值
//     * 生产唯一的产品
//     */
//    private final static Student student=new Student();
//
//    /**
//     * 静态工厂方法
//     * @return 工厂方法产生的对象
//     */
//    public static Student getStudent(){
//        return student;
//    }

    /**
     * 初始化多例静态工厂
     */
    public static Student getStudent(){
        Student student = new Student();
        student.setId(1);
        student.setName("张三");
        return student;
    }
}

配置Spring

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:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans.xsd">

        <!--Spring框架的核心配置文件-->
        <!--一个bean标签就是一个domain对象,让Spring框架帮忙创建管理这个对象
            id      唯一标识
            class   类型的具体名称,必须写包名.类名
        -->
<!--        <bean id="student" class="com.tianshi.domain.Student"/>-->

        <!--配置静态工厂-->
        <bean id="studentWithStaitcFactory" class="com.tianshi.factory.StudentStaticFactory" factory-method="getStudent"></bean>
</beans>

测试

java 复制代码
package com.tianshi.test;

import com.tianshi.domain.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class StudentWithFactoryTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        Student student=(Student)applicationContext.getBean("studentWithStaitcFactory");
        System.out.println(student);
    }
}

写到这里我明白了

懒汉/饿汉(什么时候造) -> 将实例化代码块抽象出去

静态/实例(几个工厂) -> 工厂方法是否有static,即是否只有一个工厂(类似最高权限)

单例/多例(几个产品对象) -> 每次是否生成新的产品,还是工厂只生产一个产品

下面给出常用的五种工厂

静态工厂+单例+饿汉
java 复制代码
    /**
     * 常用1:静态工厂+单例+饿汉
     * 使用final关键字保证单例不被破坏(外部引用重新赋值)
     * 用途:全局唯一工具类、配置类、Spring 单例 Bean 本质
     */
    private static final Student student =  new Student();
    public static Student getStudent(){
        return student;
    }
静态工厂+单例+懒汉
java 复制代码
    /**
     * 常用2:静态工厂+单例+懒汉
     * 工厂类外定义模板对象,当确定需要使用模板时再实例化故为懒汉
     * 用途:延迟加载、节省资源、单例对象较大时
     */
    private static Student student;
    private static Student getStudent(){
        if(student == null)student = new Student();
        return student;
    }
静态工厂+多例
java 复制代码
    /**
     *常用3:静态工厂+多例
     *用途:每次需要新对象(连接、会话、线程、实体类)
     */
    public static Student getStudent(){
        return new Student();
    }
实例工厂+多例
java 复制代码
    /**
     * 常用4:实例工厂+多例
     * 用途:不同工厂做不同初始化、策略模式、Spring 原型 Bean
     */
    public Student getStudent(){
        return new Student();
    }
实例工厂+单例
java 复制代码
    /**
     * 常用5:实例工厂+单例
     * 用途:一个工厂实例对应一个唯一对象
     */
    private static Student student;
    public Student getStudent(){
        return student;
    }

配置Spring

java 复制代码
<?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:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans.xsd">

        <!--Spring框架的核心配置文件-->
        <!--一个bean标签就是一个domain对象,让Spring框架帮忙创建管理这个对象
            id      唯一标识
            class   类型的具体名称,必须写包名.类名
        -->
<!--        <bean id="student" class="com.tianshi.domain.Student"/>-->

        <!--配置静态工厂-->
        <bean id="studentWithStaitcFactory" class="com.tianshi.factory.StudentStaticFactory" factory-method="getStudent"></bean>

        <!--配置实例工厂-->
        <bean id="studentFactory" class="com.tianshi.factory.StudentInstanceFactory"></bean>

        <bean id="studentWithInstanceFactory" class="com.tianshi.domain.Student"
        factory-bean="studentFactory" factory-method="getStudent"></bean>
</beans>
测试
java 复制代码
package com.tianshi.test;

import com.tianshi.domain.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class StudentWithFactoryTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//        Student student=(Student)applicationContext.getBean("studentWithStaitcFactory");
        Student student = (Student) applicationContext.getBean("studentWithInstanceFactory");
        student.setId(1);
        student.setName("张三");
        System.out.println(student);
    }
}

记得在实例工厂中写构造方法,否则会报错

java 复制代码
package com.tianshi.factory;

import com.tianshi.domain.Student;

public class StudentInstanceFactory {
//    /**
//     * 常用4:实例工厂+多例
//     * 用途:不同工厂做不同初始化、策略模式、Spring 原型 Bean
//     */
//    public Student getStudent(){
//        return new Student();
//    }

    /**
     * 常用5:实例工厂+单例
     * 用途:一个工厂实例对应一个唯一对象
     */
    private static Student student;
    //构造方法
    public StudentInstanceFactory(){
        student = new Student();
    }
    public Student getStudent(){
        return student;
    }
}

FactoryBean工厂创建

  • Spring的内部后门:泛型工厂接口
java 复制代码
package com.tianshi.factory;

import com.tianshi.domain.Student;
import org.springframework.beans.factory.FactoryBean;

/**
 * 基于Spring定义的工厂Bean接口,定义工厂类型
 * 接口泛型代表当前工厂生产的产品的类型
 *
 * 此种方式让代码和Spring框架耦合到一起,如果不适用spring框架,当前代码不可用
 */
public class StudentFactoryBean implements FactoryBean<Student> {
    /**
     * 工厂方法
     * @return 产品对象
     * @throws Exception
     */
    public  Student getObject() throws Exception {
        return new Student();
    }

    /**
     * 工厂生产的产品是什么
     * @return 产品类型对象
     */
    public Class<?> getObjectType() {
        return Student.class;
    }
}

配置Spring

java 复制代码
<?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:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans.xsd">

        <!--Spring框架的核心配置文件-->
        <!--一个bean标签就是一个domain对象,让Spring框架帮忙创建管理这个对象
            id      唯一标识
            class   类型的具体名称,必须写包名.类名
        -->
<!--        <bean id="student" class="com.tianshi.domain.Student"/>-->

        <!--配置静态工厂-->
        <bean id="studentWithStaitcFactory" class="com.tianshi.factory.StudentStaticFactory" factory-method="getStudent"></bean>

        <!--配置实例工厂-->
        <bean id="studentFactory" class="com.tianshi.factory.StudentInstanceFactory"></bean>

        <bean id="studentWithInstanceFactory" class="com.tianshi.domain.Student"
        factory-bean="studentFactory" factory-method="getStudent"></bean>

        <!--配置FactoryBean工厂-->
        <bean id="studentWithFactoryBean" class="com.tianshi.factory.StudentFactoryBean"></bean>
</beans>

测试

java 复制代码
package com.tianshi.test;

import com.tianshi.domain.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class StudentWithFactoryTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//        Student student=(Student)applicationContext.getBean("studentWithStaitcFactory");
//        Student student = (Student) applicationContext.getBean("studentWithInstanceFactory");
        Student student = (Student) applicationContext.getBean("studentWithFactoryBean");
        student.setId(1);
        student.setName("张三");
        System.out.println(student);
    }
}
相关推荐
梁山话事人2 小时前
Spring IOC
java·数据库·spring
魔都吴所谓2 小时前
【Linux】Ubuntu22.04 Docker+四大数据库(挂载本地)一键安装脚本
linux·数据库·docker
麦聪聊数据2 小时前
电商数据运营的最佳实践:WebSQL 如何兼顾数据分析效率与生产库安全
数据库·sql·低代码·restful
l1t2 小时前
试用postgresql的pg_duckdb插件
数据库·postgresql
oradh2 小时前
Oracle数据库实例入门概述
数据库·oracle·oracle实例·oracle实例入门·oracle基础
M--Y2 小时前
初识Redis
数据库·redis·缓存
MLGDOU2 小时前
【Qt开发】信号与槽
开发语言·数据库·qt
大黄说说2 小时前
数据库事务的ACID特性:从理论到实现的深度解析
数据库·oracle
计算机学姐3 小时前
基于SpringBoot的新能源充电桩管理系统
java·vue.js·spring boot·后端·mysql·spring·java-ee