关联完整版: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);
}
}

