目录
1. IOC的概念
1.1什么是IOC?
在百度百科中:IOC,Inversion Of Control,控制反转,属于面向对象编程的一种原则,用来降低计算机代码之间的耦合度,最常见的方式叫做依赖注入(DI);
目的(简单来说):就是通过IOC,把对象创建和对象之间的调用(就比如在一个类里面调用另一个类) 过程交给Spring来进行管理,降低耦合度(程序讲究高内聚,低耦合);
2. IOC的深层剖析
2.1 IOC用到的核心技术
- XML解析
- 设计模式中的工厂模式
- Java中的反射
2.2 IOC的底层实现原理(大致了解)
- 第一步:创建一个XML配置文件,配置需要创建的对象;(这个需要你手动)
<bean id="自己设置的名字" class="类的路径"/>
- 第二步:创建工厂类,在工厂类中返回类A的对象;(这个Spring给你完成了,你可以直接获得对象)
public class factory { //就像是简单工厂模式返回一样; public static B getA() throws ClassNotFoundException, IllegalAccessException, InstantiationException { String classvalue = "获得XML文件中的class属性值"; //然后通过反射对那个类进行加载;classvalue就是从XML中获得的类的路径; Class clazz = Class.forName(classvalue); //创建需要的对象并返回,但是如果使用工厂模式的话,就可以直接返回这个类的接口就可以了,这样以后多态就方便了; //return (A) clazz.newInstance(); /*使用下面这种方式返回,那么以后但凡是实现了接口B的都可以使用, 但是使用上面的,就只能返回A类;也就是只有调用A类才可以使用; */ return (B) clazz.newInstance(); } } interface B { } class A implements B { public void test() { System.out.println("13"); } }
下图时对上面的返回方式进行简单的解释;
2.3 IOC接口
-
在Spring中IOC接口的实现有两种方式:
一种是BeanFactory接口,Spring内部的使用接口(一般不给普通开发者不用);加载配置文件的时候,不会直接创建对象;而是在getBean()的时候才会创建对象;
另一种是ApplicationContext接口,该接口是 BeanFactory的子接口,里面的功能更加的多,主要是给普通的开发者使用;而且只要在XML中进行了类的配置,那么加载配置文件时就会把配置文件中的对象进行创建; -
IOC底层是一个对象工厂(应该就是指,是一个工厂对象,专门用来生产对象的)
-
ApplicationContext中常见的两个类,如下图:
FileSystemXmlApplicationContext这个类使用时,中间的参数主要可以理解为一个绝对路径(比如从C盘开始写);
ClassPathXmlApplicationContext这个类创建对象时,中间的参数主要可以理解为相对的路径;
2.4 IOC的Bean管理
Bean的两个操作:
- Spring创建对象;
- Spring注入属性依赖;
上面的两种操作同样的有两种方式来实现:一种是通过XML配置文件的方式来实现,第二种是通过注解的方式来实现;
3. 通过XML进行Bean管理
3.1 通过XML配置文件创建对象
首先要创建一个Spring的xml配置文件(Spring config),然后在其中使用<Bean>标签对类进行配置;
对Bean标签中的属性进行简单的记录:
id属性:
自己设置的名字(就类似与自己给这个对象建立一个标识,用于区分不同的Bean标签)
class属性:
创建的对象的类的全路径;
name属性
:和id的使用方式类似,也是用于区分bean的;
基本使用如下:(通过这中方式创建的对象,默认调用的还是无参的构造方法)
3.2 通过XML方式注入属性
DI:
注入属性;- (在Spring中有两种注入属性的方式):一种是使用set方法注入,一种是通过构造方法注入;
通过set注入:
- 创建一个类,然后在类中写好基本属性和set方法;
- 创建一个配置文件用来配置需要的属性;
<?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和class属性都已经介绍了,现在介绍以下property中使用到的属性;
name 是你自己设置的属性名;
value 是你注入的属性值,类似于默认属性值;
-->
<bean id="book" class="com.company.BookTest">
<property name="bname" value="数理化"/>
</bean>
</beans>
测试类:
public class cTest {
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("/cn/dxs/XML/TestBook.xml");
//第一个参数是之前在XML文件里面配置的id,后面是规定类型;
BookTest book = context.getBean("book", BookTest.class);
//通过上面的对象直接调用set方法,并进行赋值;
book.setBname("dd");
System.out.println(book.toString());
}
}
输出:
总结:多个属性的注入也是按照这种格式,唯一的不同点可能就是多在bean标签中多写几个property
通过构造方法的方式进行属性的注入
- 创建一个类,这个类里面有带参的构造方法;
public class BookTest {
private String Bname;
public BookTest(String bname) {
Bname = bname;
}
@Override
public String toString() {
return "BookTest{" +
"Bname='" + Bname + '\'' +
'}';
}
}
- 在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.xsd">
<!--
constructor-arg 这个标签是用来标明构造方法中的参数的;
name 构造方法中的参数名
value 是你注入的属性值,类似于默认属性值;
-->
<bean id="book" class="com.company.BookTest">
<constructor-arg name="bname" value="天才在左,疯子在右"/>
</bean>
</beans>
测试类:
public class cTest {
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("/cn/dxs/XML/TestBook.xml");
//第一个参数是之前在XML文件里面配置的id,后面是规定类型;
BookTest book = context.getBean("book", BookTest.class);
System.out.println(book.toString());
}
}
运行结果:
前面介绍的都是指,所有放进去的属性开始设置就不是空值的情况,那么如果是空值(null),该怎么设置?
其它的步骤都是一样的,唯一的不同点就是空值的属性中,在配置文件配置的时候是这样的;
<!--这就表示这个属性是空值了;-->
<property name="bname">
<null/>
</property>
还有一个就是说如果属性是一个类的引用,该怎么编写property标签;(一般就是只外部类在另一个类中调用)
<property name="bname" ref="填写另一个类的id" />
<!--解释如下:-->
<!--class user{}类;class Myclass{private user use}类-->
<!--有一个类叫user,它在配置文件中的配置;-->
<bean id="user" class="a.b.d"></bean>
<!--这是在一个类Myclass中将user作为它的属性;-->
<bean id="myclass" class="a.b.c">
<!--里面的name是属性设置时的名字;里面的ref是那个类的Bean中的id值-->
<property name="use" ref="user">
</property>
</bean>
<!--代替这里的整个xml配置文件,还有一种方式
<bean id="myclass" class="a.b.c">
<property name="use" >
<bean id="user" class="a.b.d">
<property name="user" value="jjj"/>
</bean>
</property>
</bean>
-->
接下来考虑一下,如果放进去的值带有特殊符号的时候该怎么设置,如果只是单纯什么都不做,肯定会报错的;
第一个想到的肯定是进行转移符号;(可以直接百度,一般都有,当然记得最好)
第二个就是使用<![CDATA[放入带特殊符号的值]]>就可以了;
<property name="bname">
<value>
<![CDATA[小王子]]> <!-- 目前没想写特殊符号,单纯记录吧-->
</value>
</property>
外部级联复制;
这是BookTest类;
Mian类
TestBook.xml文件
4. P名称空间注入(还是以set注入为基础)
-
在配置文件里面添加P名称空间
-
进行属性注入即可,这时就不需要再次使用property属性了;
-
运行结果:
5. IOC注入集合属性
5.1注入数组,List,Map,Set类型的属性
一:创建一个类CollectionTest作为需要创建对象的类;
public class CollectionTest {
//定义一个数组属性
private String[] arr;
//定义一个list集合属性;
private List<String> list;
//定义一个Map集合属性;
private Map<String,String> map;
//定义一个Set集合属性;
private Set<String> set;
//创建所需要的setter方法,getter 先不创建;
public void setArr(String[] arr) {
this.arr = arr;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setSet(Set<String> set) {
this.set = set;
}
@Override
public String toString() {
return "CollectionTest{" +
"arr=" + Arrays.toString(arr) +
", list=" + list +
", map=" + map +
", set=" + set +
'}';
}
}
二:在配置文件中进行设置;
<?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标签创建类的对象-->
<bean id="collectiontest" class="cn.dxs.Collection.CollectionTest">
<!--下面是对数组属性进行配置-->
<property name="arr">
<array>
<value>语文</value>
<value>数学</value>
</array>
</property>
<!--下面是对List属性进行配置-->
<property name="list">
<list>
<value>物理</value>
<value>化学</value>
</list>
</property>
<!--下面是对Map属性进行配置-->
<property name="map">
<map>
<entry key="English" value="英语"/>
</map>
</property>
<!--下面是对Set属性进行配置-->
<property name="set">
<set>
<value>历史</value>
</set>
</property>
</bean>
</beans>
三.测试类Test
public class Testdemo1 {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
CollectionTest collectiontest = context.getBean("collectiontest", CollectionTest.class);
System.out.println(collectiontest);
}
}
测试结果:
5.2 当需要往List中插入对象时,该如何做?
第一步:我们先创建一个类Book和类Library
//Book类
public class Book {
//在这个类里面创建一个简单属性;
String Bname;
public void setBname(String bname) {
Bname = bname;
}
@Override
public String toString() {
return "Book{" +
"Bname='" + Bname + '\'' +
'}';
}
}
Library类:
public class Libarary {
public List<Book> list;
//创建一个Set方法;
public void setList(List<Book> list) {
this.list = list;
}
@Override
public String toString() {
return "Libarary{" +
"list=" + list +
'}';
}
}
第二步:创建一个配置文件
<?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标签其实就是在创建一个对象,这里先创建一个book1的对象-->
<bean id="book1" class="cn.dxs.OnCollection.Book">
<property name="bname" value="巴黎圣母院"/>
</bean>
<!--再次创建应该对象book2-->
<bean id="book2" class="cn.dxs.OnCollection.Book">
<property name="bname" value="八仙过海"/>
</bean>
<!--创建一个Library类的对象-->
<bean id="library" class="cn.dxs.OnCollection.Libarary">
<property name="list">
<list>
<ref bean="book1"/>
<!--<ref bean="book2"/>-->
<!--再次创建应该对象book2-->
<bean id="book2" class="cn.dxs.OnCollection.Book">
<property name="bname" value="八仙过海"/>
</bean>
</list>
</property>
</bean>
</beans>
测试类:
public class TestLibrary {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("cn/dxs/xml/Bookconfig.xml");
Libarary library = context.getBean("library", Libarary.class);
System.out.println(library);
}
}
运行结果:
5.3 引入名称空间,将List注入简化使用
配置文件这样写:
<?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:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<util:list id="book">
<value>八仙过海</value>
<value>巴黎圣母院</value>
</util:list>
<!--创建一个Library类的对象-->
<bean id="library" class="cn.dxs.OnCollection.Libarary">
<property name="list" ref="book"/>
</bean>
</beans>
在这之中最重要的就是插入xmlns:util="http://www.springframework.org/schema/util
和最后的 http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
这样才能使用util为主的标签;