框架:
Mybatis是用来解决和数据库进行交互的。
SpringMVC是用来替代我们写这些复杂的Web逻辑的。
Spring是一个容器框架。
EJB:Enterprise Java Bean
核心关注:IOC和AOP
容器:管理所有的组件;
组件:就是你写的那些类。
DI:Dependence Injection依赖注入。
AOP:Aspect Oriented Programming面向切面编程。
进入官网:
https://spring.io/
学好Spring就是学好IOC和AOP
Spring的模块;
1、Test模块:Spring的单元测试模块
2、Core Container:核心容器(IOC)
有beans,core,context,expression
3、AOP+Aspects:面向切面编程模块
4、数据访问:Spring数据访问模块
jdbc,orm(object relation mapping),tx(事务)
5、Web:Spring开发Web应用模块
web-socket
原生web
web-mvc
Inversion Of Control
控制反转
控制:控制资源的获取方式;(被动式)
资源的获取方式分为两种:主动式和被动式。
主动式:new的形式,要什么资源自己new
被动式:资源的获取不是cxy自己创建,而是交给一个容器来创建和设置。
容器:管理所有的组件(有功能的类。)
所以控制反转的意思就是,由以前主动new的形式,变成了被动的接收。
Dependency Injection
依赖注入。
容器可以知道哪个组件运行的时候,需要另外一个类。容器通过反射的形式,将容器中准备好的对象利用反射,给它复制。
给容器中注册组件。
1、导包
核心容器的四个jar包
beans,context,core,expression
导完这些包之后,还需要一个日志包。
因为Spring运行的时候依赖一个日志包,没有就会报错。
2、写配置。
配置文件里面由Spring的IOC容器管理的所有组件。
3、创建Person类。
4、开始在ioc.xml里面写一些配置。
在ioc.xml里面注册一个Person对象,Spring会自动创建这个Person对象
最大的标签是beans。
一个bean标签,可以注册一个组件
<bean class="com.rtl.bean.Person"></bean>
<bean id="person01" class="com.rtl.bean.Person"></bean>
使用property标签为Person对象的属性赋值,
name指定属性名
value:为这个属性名赋值。
5、配置文件写好了之后,开始写测试类
ApplicationContext:这个类代表的是一个IOC容器。
ClassPathXmlApplicationContext:这是一个子类。代表通过xml文件的形式获取容器。
package com.rtl.test;
import com.rtl.bean.Person;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class IOCTest {
@Test
public void test01(){
ApplicationContext ioc = new ClassPathXmlApplicationContext("ioc.xml");
Person p1 = (Person)ioc.getBean("person01");
System.out.println(p1);
}
}
src里面的所有内容都会进入bin目录,而bin目录就是类路径的开始。
src下面直接有个ioc.xml,那么,在bin目录下直接也会有个ioc.xml
如果ioc.xml在src的com包下,那么对应bin下面的com包下也会有个ioc.xml
讲解细节:
1、ApplicationContext的继承树。
1、ClassPathXmlApplicationContext代表IOC容器的配置文件在类路径下面。
2、FileSystemXmlApplicationContext代表IOC容器的配置文件在磁盘路径下面。
我们从容器中按照id拿到了这个组件。
所以,Person对象的创建工作是由容器完成的。
问:Person对象是什么时候创建好了呢?
测试:
给Person的无参构造打印一句话:
public Person() {
System.out.println("Person对象创建了");
}
从这个测试中,我们发现了:
问:Person对象是什么时候创建好了呢?
答:
在容器创建完成的时候就已经创建好了。
执行这句话的时候,就已经创建好了。
ApplicationContext ioc = new ClassPathXmlApplicationContext("ioc.xml");
这个测试表明:
先创建好容器里面所有的对象。
第三个测试:
ioc.xml配置文件里面写了两个bean标签。
结论:
他会把容器里面所有的对象都创建好。
第四个测试:
在测试类里面,拿这个id=person01的对象拿两次,得到的这两个对象是同一个吗?
结论:是同一个对象。
同一个组件在ioc容器里面是单实例的。在容器启动的时候就已经创建准备好了。
测试五:
在容器里面跟根本没有person03这个组件。
结论:
容器中如果没有这个组件。获取组件的时候会发生异常。
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'person03' is defined
测试六:
在ioc.xml里面只有一个Person的bean标签
之前获取对象:都是通过id的名字来获取
Person p1 = (Person)ioc.getBean("person01");
现在:
Person p1 = ioc.getBean(Person.class);
但是需要注意的是:
如果通过这种形式的话,ioc.xml里面只能有一个Person的bean标签,否则会报错:
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.rtl.bean.Person] is defined: expected single matching bean but found 2: person01,person02
之前的:
<bean id="person01" class="com.rtl.bean.Person">
<property name="lastName" value="张三"></property>
<property name="age" value="18"></property>
<property name="email" value="[email protected]"></property>
<property name="gender" value="男"></property>
</bean>
通过property属性赋值。
现在:
1、给Person类加上有参构造。
2、现在的ioc.xml
<bean id="person02" class="com.rtl.bean.Person">
<constructor-arg name="lastName" value="张三"></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
<constructor-arg name="email" value="[email protected]"></constructor-arg>
<constructor-arg name="gender" value="男"></constructor-arg>
</bean>
public void test01(){
ApplicationContext ioc = new ClassPathXmlApplicationContext("ioc.xml");
Person p2 = ioc.getBean("person02",Person.class);
System.out.println(p2);
}
注意:
我们刚才讲的Person里面的属性的类型都是基本数据类型。
所以可以使用property标签进行赋值。
<bean id="car01" class="com.rtl.bean.Car">
<property name="carName" value="宝马"></property>
<property name="price" value="19000"></property>
<property name="color" value="绿色"></property>
</bean>
<bean id="person03" class="com.rtl.bean.Person">
<property name="lastName" value="张三"></property>
<property name="age" value="18"></property>
<property name="email" value="[email protected]"></property>
<property name="gender" value="男"></property>
<property name="car" ref="car01"></property>
</bean>
这个是引用外部bean的方式,现在还有内部形式:
<bean id="person03" class="com.rtl.bean.Person">
<property name="lastName" value="张三"></property>
<property name="age" value="18"></property>
<property name="email" value="[email protected]"></property>
<property name="gender" value="男"></property>
<property name="car">
<bean id="car01" class="com.rtl.bean.Car">
<property name="color" value="宝马2"></property>
</bean>
</property>
</bean>
<bean id="person04" class="com.rtl.bean.Person">
<property name="lastName" value="张三"></property>
<property name="age" value="18"></property>
<property name="email" value="[email protected]"></property>
<property name="gender" value="男"></property>
<property name="car" ref="car01"></property>
<property name="books">
<list>
<bean id="book01" class="com.rtl.bean.Book">
<property name="author" value="吴承恩"></property>
<property name="bookName" value="西游记"></property>
</bean>
</list>
</property>
</bean>
@Test
public void test01(){
ApplicationContext ioc = new ClassPathXmlApplicationContext("ioc.xml");
Person p4 = ioc.getBean("person04",Person.class);
System.out.println(p4);
List<Book> books = p4.getBooks();
for (Book book : books) {
System.out.println(book);
}
}
结论:Person里面有个属性是List<…>,使用list标签。
Book book01 = ioc.getBean("book01", Book.class);
System.out.println(book01);
使用map标签和entry标签。
一个map,就相当于new了一个LinkedHashMap
一个entry相当于K-V键值对。
这个map里面一共有四个键值对。
问
问:容器里面创建对象有顺序吗?
有的。
按照配置文件里面写的顺序来创建。
bean之间的依赖,只是改变创建的顺序。