一、IOC容器原理和概念
1.什么是IOC
ioc即控制反转,将对象创建和对象调用的过程交由Spring进行管理;
2.为什么要使用IOC
目的为了降低代码之间的耦合度;
3.IOC底层原理
结合了xml解析、工厂模式、反射,示意如下:
第一步,在xml文件中配置JavaBean信息:
<bean id="person" class="com.lazy.demo.Person"></bean>
第二步,通过工厂模式和反射创建对象:
public static Person getPerson(){
String clazzInfo = class属性值 //
Class<?> aClass = Class.forName(clazzInfo);
return aClass.newInstance();
}
4.IOC操作
IOC操作主要是进行Bean管理,而Bean管理的主要内容就是:
(1)Spring的Bean对象的创建;
(2)Spring的Bean的依赖注入;
5.IOC操作之一,Spring对象创建(基于xml)
使用IOC来创建对象只需一下步骤:
第一步,创建JavaBean:
public class Person {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
}
第二步,在xml文件中配置(创建)对象:
<bean id="person" class="com.lazy.demo.Person"></bean>
其中 bean 标签用来表示一个创建的对象,id 为bean对象的标识,class为要实例化的类的全类名,使用bean标签创建对象时要注意默认是调用空参构造器。
第三步,调用和获取创建好的对象:
public void testBegin(){
//1.加载配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("demo.xml");
//2.获取创建的对象
Person person = (Person) context.getBean("person");
//3.调用对象
System.out.println(person);
}
其中需要注意的一点是 ApplicationContext,该接口为BeanFactory的子接口,他们都可以用来获取创建的对象,但是ApplicationContext 在获取对象(即调用getBean方法时)时不创建对象,而是在配置文件时就已经创建好了对象,而BeanFactory是在获取对象时创建;
同时在加载配置文件时有两个类可以使用一个是ClassPathXmlApplicationContext和FileSystemXmlApplicationContext可以使用,区别在于前者传递的参数为在src目录下的路径,而后者为文件的绝对路径即带上盘符的路径;
6.IOC操作之二,Spring对象的属性注入
属性注入又称为依赖注入,简写为DI;
①属性注入的两种方法:
第一种使用set方法注入:
第一步,创建JavaBean:
public class Person {
private String name;
private Integer id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", id=" + id +
'}';
}
}
第二步,在配置文件中创建并注入属性:
<!--创建对象-->
<bean id="person" class="com.lazy.di1.bean.Person">
<!-- 注入属性 -->
<property name="name" value="lazy" ></property>
<property name="id" value="1001"></property>
</bean>
要注意的是使用该方法配置时一定要确保各属性的set方法已经写好,否则会报错。
第三步调用;
第二种,使用构造器来注入属性:
第一步,在类中提供带参的构造器:
public class Person2 {
private String name;
private Integer id;
public Person2(String name, Integer id) {
this.name = name;
this.id = id;
}
@Override
public String toString() {
return "Person2{" +
"name='" + name + '\'' +
", id=" + id +
'}';
}
}
第二步,在xml配置文件中使用如下方法配置:
<!-- 创建对象 -->
<bean id="person2" class="com.lazy.di1.bean.Person2">
<!-- 注入属性 -->
<constructor-arg name="name" value="lazy"></constructor-arg>
<constructor-arg name="id" value="1001"></constructor-arg>
</bean>
第三步,调用;
额外提示:使用命名空间注入,在set方法的基础上使用命名空间来注入属性:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring- beans.xsd">
<!-- 创建对象 注入属性 -->
<bean id="person3" class="com.lazy.di1.bean.Person3" p:name="lazy" p:id="1001"></bean>
②属性注入之特殊值的注入
第一种,空值的注入:
<bean id="person" class="com.lazy.di2.bean.Person">
<property name="name"><null></null></property>
<property name="id" value="1001"></property>
</bean>
第二种,特殊符号的注入:
<bean id="person2" class="com.lazy.di2.bean.Person">
<property name="name" >
<value><![CDATA[<< lazy >>]]></value>
</property>
<property name="id" value="1001"></property>
</bean>
其中<![CDATA[<< lazy >>]]>为显示字符原意:从而其中的大于和小于符号能显示出来;
③属性注入之外部Bean
属性不一定只是基本数据类型或字符串类型,也可能为其他类型,所以在注入属性时提供了将其他对象作为属性的方法;
步骤同之前,只有在第二步不同
<bean id="employee1" class="com.lazy.di3.bean.Employee">
<property name="name" value="lazy"></property>
<property name="id" value="1001"></property>
<!-- 外部引入Bean -->
<property name="dep" ref="dep1"></property>
</bean>
<bean id="dep1" class="com.lazy.di3.bean.Department">
<property name="name" value="技术部"></property>
</bean>
其中通过properties标签的rel属性来链接外部的对象;
④属性注入之内部Bean
内部Bean同外部Bean作用类似,只是操作过程不同
<bean id="employee2" class="com.lazy.di3.bean.Employee">
<property name="name" value="lazy"></property>
<property name="id" value="1002"></property>
<!-- 内部Bean -->
<property name="dep" >
<bean class="com.lazy.di3.bean.Department">
<property name="name" value="财务部"></property>
</bean>
</property>
</bean>
⑤属性注入之集合注入
属性也可以是集合如Array,List,Set,Map等集合,他们与之前最大的不同在于多个值的注入,
<bean id="student1" class="com.lazy.di4.bean.Student">
<property name="name" value="lazy"></property>
<!-- array -->
<property name="subject">
<array>
<value>English</value>
<value>Chinese</value>
<value>Math</value>
</array>
</property>
<!-- list -->
<property name="language">
<list>
<value>Chinese</value>
<value>English</value>
<value>Germany</value>
</list>
</property>
<!-- set -->
<property name="home">
<set>
<value>Beijing</value>
<value>Shanghai</value>
<value>Guangzhou</value>
</set>
</property>
<!-- map -->
<property name="school">
<map>
<entry key="小学" value="xx小学"></entry>
<entry key="中学" value="xx中学"></entry>
<entry key="高中" value="xx高中"></entry>
</map>
</property>
</bean>
补充:
(1)集合注入之外部对象:
<bean id="student2" class="com.lazy.di4.bean.Student2">
<property name="name" value="lazy"></property>
<property name="subjects">
<array>
<ref bean="chinese"></ref>
<ref bean="english"></ref>
</array>
</property>
</bean>
<bean id="chinese" class="com.lazy.di4.bean.Subject">
<property name="name" value="Chinese"></property>
</bean>
<bean id="english" class="com.lazy.di4.bean.Subject">
<property name="name" value="English"></property>
</bean>
(2)抽取集合的注入部分
第一步,在xml文件中设置一个命名空间util:
<!-- 抽取 -->
<util:list id="subjectList">
<value>111</value>
<value>222</value>
</util:list>
<bean id="student3" class="com.lazy.di4.bean.Student">
<property name="name" value="lazy"></property>
<property name="subject"><null></null></property>
<property name="school"><null></null></property>
<property name="home"><null></null></property>
<!-- 调用抽取部分 -->
<property name="language" ref="subjectList"></property>
</bean>