IOC介绍
IOC是什么
IOC(inversion of control)即“控制反转 ”,意味着将设计好的对象交给容器控制
传统的Java程序设计,直接在对象内部通过new形式来创建对象,是程序主动去创建依赖对象,即谁调用谁来创建对象,谁来初始化对象。而IOC技术是由一个专门的容器去创建对象,IOC容器来控制对象的创建而不是显式的使用new
对象的创建交给容器管理,就是控制反转。控制反转是通过容器来完成的,Spring中提供了这样一个容器,称之为IOC容器。无论是创建对象,处理对象之间的依赖,对象的创建时间还是对象创建的数量,都是在Spring为我们提供的IOC容器上配置上对象信息即可
IOC能做什么
有了IOC容器之后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象和对象之间是松耦合的,这样方便进行测试,利于功能复用,使整个体系结构变动非常灵活
由IOC容器来帮对象找相应的依赖对象并注入,而不是对象主动去找。核心点在于,资源不是由使用资源的调用方管理,而是由不使用资源的第三方管理,第三方指的就是IOC容器
资源的集中管理,实现资源的可配置和易管理
降低了使用资源双方的依赖程度,也就是说的松耦合
Spring容器管理对象Demo
1.添加Spring核心依赖
<!--Spring核心依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.3.5.RELEASE</version>
</dependency>
2.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-3.0.xsd">
</beans>
3.创建实体例(Student.java)
public class Student {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
4.IOC容器管理对象
以前是通过new形式来创建student对象的
Student student=new Student();
现在通过IOC容器,可以让IOC容器来创建和管理对象,直接在applicationContext.xml配置文件中配置对应信息
<!--使用bean标签来标识容器管理的对象
id属性标识对象名称,取名字
class属性指向需要容器管理对象类全限定名
-->
<bean id="student" class="com.wrj.maventest.Spring.IOC.Pojo.Student"/>
5.通过容器来获取Student对象
//获取IOC容器
String path="applicationContext.xml";
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(path);
Student student = (Student)applicationContext.getBean("student");
System.out.println(student);
执行结果:
以上执行结果可知,可以通过容器来获取对象实例
Spring IOC操作总结:
1.增加一个Spring配置文件
2.对XML文件进行解析
3.给定BeanFactory工厂类
4.在工厂类方法中使用反射创建bean对象
Spring中IOC容器
以上是SpringIOC容器中接口的继承关系,其中ApplicationConcext是BeanFactory的子接口,BeanFactory是SpringIOC容器所定义的最底层的接口,ApplicationConcext是BeanFactory的高级实现,并对BeanFactory的功能上做了很多的扩展,所以在大部分的工作场景下都会来使用ApplicationConcext作为IOC的容器
- BeanFacthory:BeanFactory位于最底层,提供了比较先进的配置机制,使得任何对象的配置成为可能
- ApplicationConcext:ApplicationConcext在BeanFactory上做了很多扩展实现
- BeanFactory和ApplicationConcext的区别:BeanFactory的实现是按需创建,即第一次获取bean时才创建bean,ApplicationConcext会一次性创建所有的bean,ApplicationConcext也提供了一些额外的功能,比如使Spring的AOP更容易继承,也提供了Message Resource的机制(用于处理国际化支持)和通知机制
比较BeanFactory和FactoryBean???
BeanFactory是工厂类,创建bean
FactoryBean是bean,是工厂类的对象,可以放到BeanFactory里面进行管理
ApplicationConcext容器常见实现类
- ClassPathXmlApplicationContext
ClassPathXmlApplicationContext applicationContext = new
ClassPathXmlApplicationContext(applicationContext.xml);
读取classPath,如果配置文件在当前系统类路径下,可以优先使用ClassPathXmlApplicationContext类
- FileSystemXmlApplicationContext
FileSystemXmlApplicationContext applicationContext=
new FileSystemXmlApplicationContext("d://application.xml");
读取特定路径下的资源,如果文件放在文件系统路径下,则优先选择FileSystemXmlApplicationContext类
XmlWebApplicationContext ac= new XmlWebApplicationContext("d://application.xml");
//这时并没有初始化容器
ac.setServletContext(servletContext);//需要指定ServletContext对象
ac.setConfigLocation("/WEB-INF/applicationContext.xml");
//指定配置文件路径,开头的斜线表示web应用的根目录
ac.refresh();//初始化容器
读取网络路径下的资源
容器管理对象的过程
- Spring启动时读取应用程序提供Bean配置信息,并在Spring容器中生成一份相应的Bean配置注册表;
- 根据注册表实例化Bean
- 通过配置文件装配好Bean之间的依赖关系,放到Bean缓存池,为上层应用提供准备就绪的运行环境
Bean缓存池:通过HashMap实现
Spring中Bean的实例化方式
基于XML配置方式装配Bean
bean基于配置实例化的方式有三种实现:
- 通过无参构造实例化
- 通过静态工厂方法实例化
- 通过普通工厂方法实例化
通过无参构造实例化
<!--无参构造实例化bean-->
<bean id="student" class="com.wrj.maventest.Spring.IOC.Pojo.Student"/>
如果不指定构造函数,会生成一个默认的无参构造函数
如果显性的指定一个有参构造函数,不会生成默认的无参构造函数,必须再显性指定一个无参构造函数,否则实例化对象会抛出异常
通过静态工厂方法实例化
首先,使用一个工厂的静态方法返回对象
public class StaticBeanFactory {
//提供一个获取Student对象的静态方法
public static Student getStudent(){
return new Student();
}
public static void main(String[] args) {
//通过静态工厂获取对象
Student student = StaticBeanFactory.getStudent();
}
}
在配置文件中使用工厂静态方法返回对象
<!--通过静态工厂实例化bean
class属性是工厂类的路径
factory-method:在工厂类中获取对象需要的方法
-->
<bean id="student1" class="com.wrj.maventest.Spring.IOC.StaticBeanFactory"
factory-method="getStudent"/>
通过普通工厂实例化
通过工厂创建一个非静态方法获取对象
public class CommonBeanFactory {
public Student getBean(){
return new Student();
}
public static void main(String[] args) {
CommonBeanFactory factory = new CommonBeanFactory();
factory.getBean();
}
}
配置文件中使用工厂的非静态方法返回对象
<!--通过普通工厂实例化bean-->
<!--首先创建工厂实例-->
<bean id="beanFactory" class="com.wrj.maventest.Spring.IOC.CommonBeanFactory"/>
<!--指定工厂和工厂方法实例化对象-->
<bean id="student2" class="com.wrj.maventest.Spring.IOC.Pojo.Student"
factory-bean="beanFactory" factory-method="getBean"/>
基于注解方式装配Bean(自动装配的过程)
基于注解形式进行bean的管理比XML文件形式更加简洁
通过@Component注解标注类
@Component(value="student")
//类似于XML配置文件 @Component类似于xml中的bean标签,value值类似于xml中的id属性
public class Student {
private Integer id;
private String name;
配置启动组间扫描
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--开启扫描:指定包路径或者类名,会扫描类、方法、属性上是否有注解-->
<context:component-scan base-package="com.wrj.maventest.Spring.IOC"/>
</beans>
使用 component-scan标签方式来扫描包路径及子类路径
第一步必须引入context约束,否则无法出现context标签
在Spring中主要提供了四个注解来标注bean
- @Component是通用的标签形式
- @Repository? 对Dao实例类进行标注,和数据库交互
- @Service?????? 对Service层类进行标注,处理业务逻辑
- @Controller?? 对Controller层类进行标注,接收用户连接
基于Java代码装配Bean(组件扫描)
给定一个配置类在配置类上添加@Configuration,@Configuration表明当前类是一个配置类,告诉Spring上下文如何创建bean细节
@Configuration
//表明当前类是配置类
public class TestConfig {
}
将交给Spring管理的类声明为bean,编写一个方法,方法创建所需要的的bean实例,给方法添加上@Bean注解
@Bean(name="student4")
//name类似于xml中的id属性
public Student student(){
return new Student();
}
@Bean注解会告诉Spring这个方法会返回一个对象,这个对象会被注册到Spring中
Spring中DI介绍
DI(Dependency Injection)即依赖注入,对象之间的依赖由容器在运行期决定,即容器动态的将某个依赖注入到对象之中
基于XML配置注入依赖
有参构造函数注入依赖
bean类需要实现有参构造函数
/**
* 有参构造函数
*/
public Student(Integer id, String name) {
this.id = id;
this.name = name;
}
在配置文件中配置参数通过有参构造函数给对象属性赋值
<!--通过有参构造形式注入依赖-->
<bean id="student5" class="com.wrj.maventest.Spring.IOC.Pojo.Student">
<!--id属性注入-->
<constructor-arg name="id" value="11"/>
<!--name属性注入-->
<constructor-arg name="name" value="wrj"/>
</bean>
有参构造是使用construct-arg标签
set方法注入依赖
给对象属性提供set方法
public void setId(Integer id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
在配置文件中通过set方法赋值
<!--通过set方法注入依赖-->
<bean id="student6" class="com.wrj.maventest.Spring.IOC.Pojo.Student">
<property name="id" value="12"/>
<property name="name" value="gy"/>
</bean>
通过set方式使用的是property标签
注入的依赖也可以是自定义的类型
<!--注入自定义类型-->
<bean id="user" class="com.wrj.maventest.Spring.IOC.Pojo.User">
<constructor-arg name="name" value="dd"/>
</bean>
<bean id="student7" class="com.wrj.maventest.Spring.IOC.Pojo.Student">
<property name="id" value="12"/>
<property name="name" value="gy"/>
<!--value属性:将参数按照String类型解析
ref属性:将参数解析成Spring中管理的对象的ID值
-->
<property name="user" value="user"/>
</bean>
自定义类型也是要交给Spring管理,如何获取管理对象实例
使用ref属性来获取值,该ref会自动识别为Spring中对象的名称
使用value属性来获取值,Spring认为仅仅是一个字符串值
依赖也可以是集合类型
<!--注入集合类型-->
<bean id="student8" class="com.wrj.maventest.Spring.IOC.Pojo.Student">
<!--注入list类型-->
<property name="coursrName">
<list>
<value>语文</value>
<value>数学</value>
<value>英语</value>
</list>
</property>
<!--注入Map类型-->
<property name="coursrScore">
<map>
<entry key="语文" value="98"/>
<entry key="数学" value="98"/>
<entry key="英语" value="98"/>
</map>
</property>
</bean>
基于注解形式注入依赖
@Value:注入普通类型属性
@Resource:注入对象类型
@Autowired:注入对象类型,默认按照类型注入
@Value:
该注解只能添加到普通类型上,@Value(“1”)注解中可以赋值完成对基础属性的依赖注入
@Component(value="student3")
//类似于XML配置文件 @Component类似于xml中的bean标签,value值类似于xml中的id属性
//@Repository
//@Service
//@Controller
public class Student {
@Value("1")
private Integer id;
@Resource:
该注解是注入对象类型
该注解是由java提供的,不是由Spring框架提供的,默认按照类的类型来查找并注入类
@Component(value="student3")
//类似于XML配置文件 @Component类似于xml中的bean标签,value值类似于xml中的id属性
public class Student {
//自定义类型
@Resource(name="user")
private User user;
@Autowired:
该注解是注入对象类型的,是Spring框架提供的,按照名称来查找并注入类
@Component(value="student3")
public class Student {
//自定义类型
@Autowired
private User user;
|