Spring跟Tomcat很像,Tomcat管理servlet,filter 和 listener,而Spring管理所有的组件,比Tomcat丰富得多。
一、使用Spring模仿Tomcat
1.创建MockHttpServlet,实现Serializable序列化接口
public class MockHttpServlet implements Serializable{
private static final long serialVersionUID = 1L;
public void init() {}
public void service() {}
public void destroy() {}
}
2.创建子类MockServlet1和MockServlet2,重写service方法
public class MockServlet1 extends MockHttpServlet{
private static final long serialVersionUID = 1L;
public void service() {
//System.out.println("servlet`1");
mockServlet.service();
}
}
3.在applicationContext.xml配置文件使用<bean>将组件注册到Spring容器
<!-- spring是一个容器,在框架架构中,会将很多组件交给spring控制 -->
<!-- servlet-name servletclass -->
<bean id="servlet1" class="net.seehope.spring.demo.ioc.mock.MockServlet1"></bean>
<bean id="servlet2" class="net.seehope.spring.demo.ioc.mock.MockServlet2"></bean>
4.创建Application测试类
public class Application {
public static void main(String[] args) {
//使用spring去模拟Tomcat;
//IOC inverse of control 控制反转,将bean交给spring管理控制;
//通过读取配置文件,把配置文件中的所有组件初始化,放到ac这个对象中;
//ClassPathXmlApplicationContext()读取类路径下的spring配置文件,创建spring容器ac,
//会将容器中定义的所有bean都会一起初始化;
ApplicationContext ac= new ClassPathXmlApplicationContext("applicationContext.xml");
ac.getBean("mockServlet1");
//通过ac对象,将需要的组件从Spring容器中取出(如果scope类型为single,
//多次则取出都是同一对象);
MockHttpServlet ms1=(MockHttpServlet) ac.getBean("mockServlet1");
//执行该组件的service()方法;
ms1.service();//运行结果:servlet`1
}
}
注: pojo类知识对数据进行封装,不需将pojo类交给Spring管理。同时,不能在Spring容器中定义变量(多线程),可存放常量。 Spring 管理的都是层级对象:Dao层,Service层,Web层。默认都是单例的。
二、IOC 控制反转和 DI 依赖注入
控制反转和依赖注入(IOC和DI):一般使用其他人写好的bean时用到,并提供初始化配置
IOC(Inversion of Control):控制反转,将组件注册到Spring容器中(也就是写<bean>标签)
<!-- IOC:控制反转 servlet-name servletclass
prototype 原型,每一个getBean都相当于重新new了一个bean
single 相当于每一次getBean都从spring容器中,取出同一个对象.
scope 控制组件的 生命周期. -->
<!-- IOC和DI 使用其他人写好的bean,并提供初始化配置 按照bean的标准去写-->
<bean id="mockServlet1" name="1,2,3" scope="prototype"
init-method="init" destroy-method="destory"
class="net.seehope.spring.demo.ioc.mock.MockServlet1">
DI(Dependency Injection):依赖注入,在Spring创建这个<bean>时,可以将一些默认值注入(类似初始化参数)
<bean id="mockServlet1" name="1,2,3" scope="prototype"
init-method="init" destroy-method="destory"
class="net.seehope.spring.demo.ioc.mock.MockServlet1">
//提供初始化参数的两种方法
<!-- 1.提供get/set 并通过property标签注入 -->
<property name="id" value="10"></property> //通过组件对象ms1.getId()获得的值为10
<!-- 2.通过<constructor-arg>一般不用
<constructor-arg name="id" value="10"></constructor-arg>
<constructor-arg name="ids" ></constructor-arg>
<constructor-arg name="maps" ></constructor-arg> -->
<property name="ids"> //通过/通过组件对象ms1.getId()获得的值为一个集合,
//使用list接收再遍历输出
<list>//list是property的子标签,描述的是集合
<value>10</value>
<value>20</value>
<value>30</value>
<value>40</value>
<value>50</value>
<value>60</value>
</list>
</property>
<property name="username" value="mt"></property>
<property name="maps">
<map>
<entry key="name" value="mt"></entry>
</map>
</property>
<!-- 如果是引用类型,通过ref进行注入 ref的对象也必须是spring的bean(bean中的id) -->
<property name="mockServlet2" ref="mockServlet2"></property>
</bean>
<bean id="mockServlet2"
class="net.seehope.spring.demo.ioc.mock.MockServlet2">
</bean>
Java Bean的标准
javaBean(只是规范了代码的格式)
- 1.必须要有包
- 2.必须有空构造器
- 3.必须提供get/set
- 4.覆盖序列化接口
所以如果我们在网上找到别人的bean,就可以引入工程中,并提供使Ta起作用的初始化参数,就可以成为自己的bean
三、Spring 注解方式
在项目中,通过注解注入的,不需要提供Getters和Setters方法或构造器。
1.开启注解扫描功能:
1)在applicationContext.xml文件中,点击命名空间Namespaces,勾选context选项
2)插件会帮我们将约束加进去
3)在开启注解扫描之前先看下我们的项目结构:
2. 在applicationContext.xml文件中,插入<context:component-scan>标签,属性base-package="net.xikee"表示net.xikee这个包以及后面所有的子包都会被扫描
<?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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<!-- 开启对于Spring 组件注解扫描的支持 -->
<context:component-scan base-package="net.xikee"></context:component-scan>
</beans>
3.spring中,将当前类注册到Spring容器中的注解有四种,分别如下:
@controller(控制层)
@service (业务层)
@repository (Dao层)
@component (其它层使用 )
在类顶部加上@Controller,相当于在applicationContext.xml文件中写上:
<bean id="mockServlet1" class="net.seehope.spring.demo.ioc.mock.MockServlet1"></bean>
spring 会默认将当前的类名首字母改为小写后作为 bean 的 id,注册到spring容器中。若改为@Controller(“xikee”),则当前类的id为xikee,此时不再有默认id。
4. @Autowired 和 @Qualifier 注解------注入的是引用类型
已知MockServlet1类是MockHttpServlet类的子类。
@Autowired
private MockHttpServlet mockServlet2;
@Autowired会根据两个依据去找,首先会spring中找所有MockHttpServlet 类的所有子实现(本身的实现或子实现,会找到MockServlet1 、2、3…)第二步按照属性名匹配。
找到子类,将mockServlet2传进spring容器中找有没有已注册的bean。
@Autowired
@Qualifier(“mockServlet3”)
private MockHttpServlet mockServlet;
这种方式则不需MockHttpServlet的属性名进行指定,而是通过@Quelifier注解对匹配的对象进行指定(mockServlet 3)
mockServlet.service(); //此时调用的是mockServlet3中的service(方法)
@Controller
@Scope(scopeName="single")
public class MockServlet1 extends MockHttpServlet{
@Autowired
@Qualifier("mockServlet3")
private MockHttpServlet mockServlet;
public void service() {
//System.out.println("servlet`1");
mockServlet.service(); //此时调用的是mockServlet3中的service(方法)
}
}
如果当前类在Spring中有多个子实现(验证码生成的逻辑会有多种实现:短信验证、邮箱验证等等),则可以通过 @Qualifier 注解指定具体是哪一个实现。