IOC概念
( Inversion of Control,缩写为 IoC),是面向对象编程中的一种设计原则,可以用来降低计算机代码之间的耦合度。
简单来说Spring中的IOC控制反转就是将对象实例化对象的控制权,由手动的new,转为交给Spring框架通过反射机制,进行对象的实例化。
在Spring入门中我们已经使用了xml配置来控制对象的创建,实现了控制反转。
容器的使用
前面说了控制反转就是将创见对象的控制权由new,转为交给Spring框架通过反射机制,进行对象的实例化,Spring容器进行实例化后会将创建的实例对象放入Spring容器,那么Spring容器到底是什么东西?
概念理解
容器,容器,顾名思义就是用来装东西的;如我们生活中的水杯,水桶、水盆等等,所以我们的Spring容器也是用来装东西的;水杯、水桶用来装水,而我们的Spring容器就是用来装对象实例的。
IOC 容器的体系结构
-
spring容器
Spring的容器有两个
- BeanFactory
- ApplicationContext
-
两者的关系
可以看出,他们两个都是接口,并且ApplicationContext是BeanFactory的子接口。
在BeanFactory中提供了配置框架和基本功能
在ApplicationContext中增加了更多针对企业的功能。
-
两者的区别
创建对象的时间点不一样。
ApplicationContext
:只要一读取配置文件,默认情况下就会创建对象,类似与单例模式中的饿汉式。BeanFactory
:什么时候使用,什么时候创建对象,类似与单例模式中的懒汉式。
IoC 容器实例化的方式
上面已经知道 Spring 的容器是通过一个接口 org.springframework.context.ApplicationContext
表示,并负责实例化,配置和组装 Bean 对象。容器通过读取 xml 文件中的配置信息来获取关于实例化对象,配置属性等命令。
而 ApplicationContext
只是一个接口,我们通常创建 ClassPathXmlApplicationContext
的实例或者 FileSystemXmlApplicationContext
的实例。
前者是从类路径中获取上下文定义文件,后者是从文件系统或 URL 中获取上下文定义文件。
-
从类路径下读取Spring配置文件,创建Spring容器
public void userSaveTest() { //创建spring容器,参数指定spring配置文件的全名 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); //可以使用多态方式也可以 /* ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); */ }
-
从电脑本地读取配置文件,创建Spring容器
public void userSaveTest() { //创建spring容器,参数指定spring配置文件的全名 FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("D:\\applicationContext.xml"); }
bean 标签中的属性介绍
我们知道Bean标签的作用就是在框架启动加载配置文件的时候,根据配置的类的全限定名,创建实例对象,放入Spring容器进行统一管理,
Bean标签回顾
<bean id="userService" class="com.myproject.service.impl.UserServiceImpl"/>
以上我们只用到了id属性和class属性,那么来看一下是否还有其他属性。
常用属性介绍
属性 | 描述 |
---|---|
id | 定义配置的Bean标签的唯一标识 |
name | 同id属性 |
class | 表示要描述的类,也就是当加载spring配置文件的时候,要根据此属性指定的类的全限定名创建的实例对象。 |
factory-bean | 主要用于工厂模式实例化 bean 的时候使用,这个属性用于引用配置的工厂Bean |
factory-method | 主要用于工厂模式实例化 bean 的时候使用,这个属性表示引用工厂Bean中的指定方法。 在普通工厂模式下factory-bean与factory-method结合使用,静态工厂时单独使用factory-method |
init-method | Bean初始化的时候,指定执行的方法。 |
destroy-method | Bean销毁的时候,指定执行的方法。 |
scope | 指定配置的Bean的作用范围,一般用多例还是单例来表述它。 |
lazy-init | 懒加载 |
autowire | 依赖注入 |
depends-on | 依赖于某个实例 |
id和name属性
用于定义Bean的唯一标识,方便我们获取。
配置文件代码
<?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="user" name="user2" class="com.wyan.entity.User" ></bean>
</beans>
测试类代码
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
System.out.println(context.getBean("user"));
System.out.println(context.getBean("user2"));
}
无论是使用id还是使用name,都能从Spring容器中获取Bean
class 属性
Spring的底层是通过反射来创建的实例对象,但是他不知道创建哪个类的实例对象啊;所以通过Class属性指定要创建的实例对象的全限定类名。
factorybean 和 factorymethod 属性
这两个属性主要用于工厂模式实例化 bean 的时候使用
-
使用静态工厂模式获取Bean
静态工厂类代码
//方法和参数都是静态的 public class User { private static User user = new User(); private User() {} public static User createInstance() { return user; } }
applicationContext配置
<!-- 通过factory-method属性,引用User工厂类中的createInstance方法,该方法返回值是一个user对象; 所以当我们使用Bean标签的id获取Bean的时候,得到的是createInstance方法的返回值 -> user对象 --> <bean id="user" class="com.wyan.entity.User" factory-method="createUserInstance"/>
-
使用普通工厂获取Bean
普通工厂类代码
public class BeanFactory { private static User1 user1 = new User1(); private static User2 user2 = new User2(); public User1 createUser1() { return user1; } public User2 createUser2() { return user2; } }
applicationContext配置
<!--spring实例化工厂对象 用于创建java实例 --> <bean id="beanFactory" class="com.wyan.factory.BeanFactory"></bean> <!-- 被工厂创建的对象实例 --> <bean id="user1" factory-bean="beanFactory" factory-method="createUser1"/>
先要配置工厂Bean,然后引用工厂Bean的id,使用factory-method属性,引用工厂Bean中的方法,得到该方法的返回值,也就得到了User1实例对象
init-method 和 destroy-method 属性的使用
init-method 就是 bean 被初始化后执行的方法,destory-method 就是 bean 被销毁执行的代码。
-
测试代码User类
public class User { public User(){ System.out.println("我被spring实例化了"); } public void initMethod(){ System.out.println("user类实例化时候执行的代码"); } public void destoryMethod(){ System.out.println("user类实例被销毁时候执行的代码"); } }
-
applicationContext.xml配置
<bean id="user" class="com.wyan.entity.User" init-method="initMethod" destroy-method="destoryMethod" ></bean>
-
测试代码
public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); }
-
结果
scope 属性
常用属性值
默认为singleton 单例
-
singleton:单例创建对象,当创建Spring容器的时候,对象就会创建,销毁Spring容器的时候,对象也就销毁;每次从Spring容器中获取的对象都是同一个。
-
prototype:多例创建对象,当获取对象的时候,才会创建对象,销毁Spring容器的时候,对象不会销毁,由其它机制管理销毁;每次从Spring中获取的对象都不是同一个。
<!--单例--> <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl" scope="singleton"/> <!--多例--> <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl" scope="prototype"/>