目录
一、本章目标
- 什么是spring,spring ioc的用途
- Spring的注入方式
- Spring与web容器的整合原理
二、spring ioc的用途
Spring简介
Spring是一个开源框架,它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。
Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。
然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。
目的:解决企业应用开发的复杂性
功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能
范围:任何Java应用
简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
spring包含的模块:
spring插件安装失败及解决方案:
1.Spring介绍:
Spring全家桶 架构方案层面
spring struts Hibernate
spring springmvc mybatis
springboot dubbox
SpringCloud技术层面
安全技术方面:Shiro springSecurity
数据库层面:hibernate/mybatis SpringDataJpa
消息中间件:activityMQ、RabbitMQ、kaffka spring..MQ
....
2. 什么是控制反转(或依赖注入)
控制反转(IoC=Inversion of Control)IoC,用白话来讲,就是由容器控制程序之间的(依赖)关系,而非传统实现中,由程序代码直接操控。这也就是所谓“控制反转”的概念所在:(依赖)控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转。
IoC还有一个另外的名字:“依赖注入 (DI=Dependency Injection)” ,即由容器动态的将某种依赖关系注入到组件之中
案例:实现Spring的IoCIOC/DI
将以前由程序员实例化对象/赋值的工作交给了spring处理3. 如何在spring当中定义和配置一个JavaBean(使用无参构造方法+set方法创建一个JavaBean)
3.1 id:在容器中查找Bean的id(唯一、且不能以/开头)
3.2 class:bean的完整类名
3.3 name:在容器中查找Bean的名字(唯一、允许以/开头、允许多个值,多个值之间用逗号或空格隔开)
3.4 scope:(singleton|prototype)默认是singleton
3.4.1 singleton(单例模式):在每个Spring IoC容器中一个bean定义对应一个对象实例
3.4.2 prototype(原型模式/多例模式):一个bean定义对应多个对象实例
3.4 abstract:将一个bean定义成抽象bean(抽象bean是不能实例化的),抽象类一定要定义成抽象bean,非抽象类也可以定义成抽象bean
3.5 parent:指定一个父bean(必须要有继承关系才行)
3.6 init-method:指定bean的初始化方法
3.7 constructor-arg:使用有参数构造方法创建javaBean
注1:struts2的Action请使用多例模式
4. 简单属性的配置:
8+1+3
8基础数据+String+3个sql
java.util.Date
java.sql.Date
java.sql.Time
java.sql.Timestamp
通过<value>标签赋值即可
5. 复杂属性的配置
5.1 JavaBean
ref bean=""
5.2 List或数组
5.3 Map
5.4 Properties
6. 针对项目,配置文件路径的2种写法
ApplicationContext
String path = "applicationContext.xml";
String path = "classpath:applicationContext-*.xml";//src
String[] path = new String[] { "applicationContext-a.xml", "applicationContext-b.xml" };//分模块开发
7. spring与web项目的集成WEB项目如何读取spring上下文
通过监听器实现ServletContextListener
contextConfigLocation:classpath:applicationContext-*.xml
8. log4j2
9. spring.pom
spring-context
spring-orm
spring-web
spring-aspects
注:创建spring的XML文件时,需要添加beans/aop/tx/context标签支持
资源:
spring tool suite官方下载地址:http://spring.io/tools/sts/all
很详细的网文在线安装介绍:http://www.cnblogs.com/liuyungao/p/6213997
1.1 中间层框架、万能胶
struts2
spring
hibernate
1.2 容器框架
JavaBean 项目中的一个个类
IOC和AOP
Spring ioc解决的问题
基于Maven所引入的jar包,当然如果大家不习惯使用Maven来引入jar包的话,可以在https://mvnrepository.com/ 中央仓库(所有jar包)根据下方<artifactId></artifactId>所包裹的jar名进行查找 <spring.version>5.0.1.RELEASE</spring.version> 包裹的5.0.1.RELEASE版本的jar包
——建议大家可以使用Maven去引入jar包,这样风更加方便快捷
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ajf</groupId>
<artifactId>T276_Spring</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>T276_Spring Maven Webapp</name>
<url>http://maven.apache.org</url>
<!-- tomcat整合ioc容器 -->
<properties>
<spring.version>5.0.1.RELEASE</spring.version>
<javax.servlet.version>4.0.0</javax.servlet.version>
<junit.version>4.12</junit.version>
</properties>
<dependencies>
<!-- 2、导入spring依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 5.1、junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- 5.2、servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${javax.servlet.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>T276_Spring</finalName>
<plugins>
<!--第一步就是配置maven-compiler-plugin插件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
UserService 接口
/** * 实现业务功能的接口 * 完成的需求:给客户添加一个文件上传的接口,实现文件上传的功能 * 客户在使用了之后,觉得上传文件的速度太慢了,要求提升该功能的性能 * @author Administrator * */ public interface UserService { public void upload(); } |
UserService ——UserService接口实现类1
package com.javaxl.ioc.service; /** * 第一个版本的:程序员实现功能完写的实现类,并没有考虑到性能问题 * * @author Administrator * */ public class UserServiceImpl1 implements UserService { @Override public void upload() { // 性能不行的话,会在当前方法进行代码修改,比如说,之前没有用到缓冲流,现在在当前方法中使用缓冲流,来提升 // 性能 System.out.println("v1.0:程序员实现功能完写的实现类,并没有考虑到性能问题"); } } |
UserService ——UserService接口实现类2
/** * 解决客户投诉问题,上传功能的性能问题 v2.0 * @author Administrator * */ public class UserServiceImpl2 implements UserService { @Override public void upload() { System.out.println("解决客户投诉问题,上传功能的性能问题 v2.0"); } } |
UserAction
package com.javaxl.ioc.web; import com.javaxl.ioc.service.UserService; import com.javaxl.ioc.service.UserServiceImpl1; public class UserAction { private UserService userService = new UserServiceImpl1(); public void test1() { userService.upload(); } } |
TeacherAction
package com.javaxl.ioc.web; import com.javaxl.ioc.service.UserService; import com.javaxl.ioc.service.UserServiceImpl1; public class TeacherAction { private UserService userService = new UserServiceImpl1(); public void test1() { userService.upload(); } } |
目前存在问题:如果说多个action类要使用同一个service接口,那么一旦service实现类发生改变那么,就需要程序员改动每一个action中的代码,去改变该service接口的具体应用的实现类;
Springioc就解决上述问题:
实现了一处改动,多处受益的结果
具体代码如下
UserAction
package com.javaxl.ioc.web; import com.javaxl.ioc.service.UserService; public class UserAction { private UserService userService; public UserService getUserService() { return userService; } public void setUserService(UserService userService) { this.userService = userService; } public void test1() { userService.upload(); } } |
TeacherAction
package com.javaxl.ioc.web; import com.javaxl.ioc.service.UserService; public class TeacherAction { private UserService userService; public UserService getUserService() { return userService; } public void setUserService(UserService userService) { this.userService = userService; } public void test1() { userService.upload(); } } |
spring-context.xml ——spring配置xml文件
<?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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.3.xsd"> <!-- 此处进行对Spring.xml的Spring的Ioc配置 --> <!--配置实现接口实现类:UserServiceImpl2--> <bean class="com.javaxl.ioc.service.UserServiceImpl2" id="userService"></bean> <!--配置使用接口方法的类:UserAction--> <bean class="com.javaxl.ioc.web.UserAction" id="userAction"> <!--此处功能为对应的属性userService进行反转注入--> <!--property:一般需要为对应的注入属性给予set方法--> <!-- name:com.javaxl.ioc.web.UserAction中的属性 <property name="userService" ref="userService"></property> </bean> <!--配置使用接口方法的类TeacherAction--> <bean class="com.javaxl.ioc.web.TeacherAction" id="teacherAction"> <property name="userService" ref="userService"></property> </bean> </beans> |
测试类:
package com.javaxl.ioc.test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.javaxl.ioc.web.TeacherAction; import com.javaxl.ioc.web.UserAction; public class IocTest { @SuppressWarnings("resource") public static void main(String[] args) { //由于/spring-context.xml 存在于src/main/resources目录下,因此需要加/ //ClassPathXmlApplicationContext():建模 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml"); //getBean():通过所配置好的spring-context.xml中获取UserAction对象 UserAction userAction = (UserAction) applicationContext.getBean("userAction"); //调用UserAction中的test1()方法 userAction.test1(); TeacherAction teacherAction = (TeacherAction) applicationContext.getBean("teacherAction"); teacherAction.test1(); } } |
三、Spring的注入方式
package com.javaxl.ioc.web; import java.util.List; import com.javaxl.ioc.service.UserService; /** * spring的注入方式 1、set注入(提供set方法) 2、构造注入(提供构造方法) 3、自动装配(spring-context.xml上方beans default-autowire="byType") * byType:spring框架根据接口自动在spring的上下文中去寻找与之匹配的实现类,进行自动注入; * 如果在spring上下文中有连个匹配上的,那会报错 * byName: * spring框架根据接口的名字(属性名)去上下文进行寻找,是通过Bean标签的id进行寻找; * * spring的注入类型: 1、八大基本类型 2、引用类型(String,Array、集合) 3、自定义的引用类型(UserService) * * @author Administrator * */ public class UserAction { private UserService userService; private String uname; private int age; private List<String> hobby; public void test2() { System.out.println(this.uname); System.out.println(this.age); System.out.println(this.hobby); } public UserAction(String uname, int age) { super(); this.uname = uname; this.age = age; } public UserAction() { super(); } // public String getUname() { // return uname; // } // // public void setUname(String uname) { // this.uname = uname; // } // // public int getAge() { // return age; // } // // public void setAge(int age) { // this.age = age; // } public List<String> getHobby() { return hobby; } public void setHobby(List<String> hobby) { this.hobby = hobby; } public UserService getUserService() { return userService; } public void setUserService(UserService userService) { this.userService = userService; } public void test1() { userService.upload(); } } |
package com.javaxl.ioc.web; import com.javaxl.ioc.service.UserService; /** * byName * @author Administrator * */ public class TeacherAction { private UserService userService2; public UserService getUserService2() { return userService2; } public void setUserService2(UserService userService2) { this.userService2 = userService2; } public void test1() { userService2.upload(); } } |
<?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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:task="http://www.springframework.org/schema/task" default-autowire="byName" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.3.xsd"> <!--自动装配 byName注入--> <bean class="com.javaxl.ioc.service.UserServiceImpl1" id="userService"></bean> <bean class="com.javaxl.ioc.service.UserServiceImpl2" id="userService2"></bean> <bean class="com.javaxl.ioc.web.UserAction" id="userAction"> <!--自动装配 byType注入:两者接口实现类,只有一个,且里面的方法被:TeacherAction和UserAction调用--> <bean class="com.javaxl.ioc.service.UserServiceImpl1" id="userService"></bean> <!--<bean class="com.javaxl.ioc.service.UserServiceImpl2" id="userService2"></bean>--> <bean class="com.javaxl.ioc.web.UserAction" id="userAction"> <!--自动装配的作用:可以省略:<!-- <property name="userService" ref="userService"></property> -->--> <!-- set注入 :property--> <!--常用八大基本类型赋值方式--> <!-- <property name="userService" ref="userService"></property> --> <!-- <property name="age" value="22"></property> --> <!-- <property name="uname" value="zs"></property> --> <!-- 构造注入:constructor-arg --> <!--常用八大基本类型赋值方式--> <constructor-arg name="age" value="22"></constructor-arg> <constructor-arg name="uname" value="ls"></constructor-arg> <!--为list集合hobby进行赋值方式--> <property name="hobby"> <list> <value>象棋</value> <value>围棋</value> <value>军旗</value> </list> </property> </bean> <bean class="com.javaxl.ioc.web.TeacherAction" id="teacherAction"> <!-- <property name="userService" ref="userService"></property> --> </bean> </beans> |
四、Spring与web容器的整合原理
实现的目标:
在用户每一次发送任意请求,在对应请求处理代码中可以获取到spring容器中配置的任意的JavaBean,从而可以对应的javabean中定义的方法
实现思路:
- 在tomcat启动的时候自动去加载spring的上下文(ApplicationContext)
- 利用监听器去把spring的上下文放到tomcat的上下文中
- 为了解决框架的配置文件冲突的问题,我们需要动态指定spring上下文的配置文件名称;
package com.javaxl.ioc.listener; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** *上下文监听(作用:建模的过程中(对于公司开发一个完整的项目而言)是非常消耗时间的,因此为了节省资源,将建模的只初始化一次 * @author Administrator * */ @WebListener public class SpringLoadListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { System.out.println("tomcat启动会加载的方法......"); // 1、在tomcat启动的时候自动去加载spring的上下文(ApplicationContext) ServletContext servletContext = sce.getServletContext(); String springLocationXml = servletContext.getInitParameter("springLocationXml"); if(springLocationXml == null || "".equals(springLocationXml)) { springLocationXml = "/spring-context.xml"; } System.out.println("当前spring上下配置文件是:"+springLocationXml); ApplicationContext applicationContext = new ClassPathXmlApplicationContext(springLocationXml); servletContext.setAttribute("SPRING_WEB_KEY", applicationContext); } } |
web.xml
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <display-name>Archetype Created Web Application</display-name> <!--配置所定义好的监听器--> <context-param> <param-name>springLocationXml</param-name> <param-value>/spring-xl.xml</param-value> </context-param> </web-app> |
package com.javaxl.ioc.web; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.context.ApplicationContext; /** * spring上下文与tomcat上下文是否整合完毕 * * @author Administrator * */ @WebServlet("/demo") public class SpringWebServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //首先获取上下文监听器所传递过来的对spring-context.xml建模对象springContext ApplicationContext springContext = (ApplicationContext) req.getServletContext().getAttribute("SPRING_WEB_KEY"); //获取TeacherAction对象 TeacherAction bean = (TeacherAction) springContext.getBean("teacherAction"); bean.test1(); } } |