目录
一、前言
1.1.Spring简介
1.2.使用Spring的优点
1.3.Spring组成
二、Spring之IOC详解
2.1.IOC理论推导
2.1.1.IOC分析实现
2.1.2.IOC本质
2.2.Maven项目导入Jar包
2.3.依赖注入
2.3.1.Set注入(重点)
2.3.2.构造注入
无参构造创建对象
有参构造创建对象
2.4.自动装配
byName(按名称自动装配)
byType (按类型自动装配)
2.5.spring与web容器的整合
一、前言
1.1.Spring简介
Spring翻译过来就是春天的意思,它的出现也是给广大程序员带来了春天🍃。
Spring框架最初由Rod Johnson创建,他于2002年写了一本名为《Expert One-on-One J2EE Design and Development》的书,书中详细介绍了一些与J2EE技术有关的设计模式和最佳实
践。该书的成功激发了Rod Johnson继续探索J2EE开发的方法,最终他开发了Spring框架。
2004年,Spring框架发布了第一个正式版本1.0,这个版本包括IoC容器、AOP、数据访问等核心特性。
Spring官网http:// http://spring.io/Spring官方下载地址https://repo.spring.io/libs-release-local/org/springframework/spring/
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.0.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.0.RELEASE</version> </dependency>
1.2.使用Spring的优点
Spring是一个开源框架,它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。
Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。
然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。
目的:解决企业应用开发的复杂性
功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能
范围:任何Java应用
简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
1.3.Spring组成
Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式 .
组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:
- 核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转(IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
- Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。
- Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向切面的编程功能 , 集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理任何支持 AOP的对象。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖组件,就可以将声明性事务管理集成到应用程序中。
- Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。
- Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。
- Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
- Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。
二、Spring之IOC详解
2.1.IOC理论推导
我们先新建一个Maven项目来进行我们的IOC理论推导
2.1.1.IOC分析实现
给客户添加一个文件上传的接口,实现文件上传的功能
1.建立一个UserService接口
public interface UserService {
public void update();
}
2.实现接口完成功能
public class UserServiceImpl implements UserService {
public void update() {
System.out.println("V1.0:程序员实现功能完写的实现类");
}
}
3.客户要求更改需求
public class UserServiceImpl2 implements UserService {
public void update() {
System.out.println("V2.0:解决客户投诉问题,更改需求");
}
}
4.编写Userservlet
public class UserAction {
private UserService userService= new UserServiceImpl2();
public String Update(){
userService.update();
return "list";
}
}
在公司很多时候客户在上午提的需求,你做完了下午就不要了,那你只能修改UserServlet的接口实现把2变为1,一个类修改起来容易,10..50..100..这种方式就根本不适用, 甚至反人类 , 每次变动 , 都需要修改大量代码 . 这种设计的耦合性太高了, 牵一发而动全身 。
如果使用Spring, 以前所有东西都是由程序去进行控制创建 , 而现在是由我们自行控制创建对象 , 把主动权交给了调用者 。 程序不用去管怎么创建,怎么实现,它只负责提供一个接口 。
2.1.2.IOC本质
控制反转IOC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IOC的一种方法,也有人认为DI只是IOC的另一种说法。没有IOC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。
耦合对象:
解耦对象:
理想系统:
IOC是Spring框架的核心内容,使用多种方式完美的OC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配IOC。
Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从Ioc容器中取出需要的对象。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。
2.2.Maven项目导入Jar包
spring 需要导入commons-logging进行日志记录 , 我们利用maven ,他会自动下载对应的依赖项
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.10.RELEASE</version>
</dependency>
2.3.依赖注入
2.3.1.Set注入(重点)
userAction.java
public class UserAction {
private UserService userService;
private String name;
private String[] books;
private List<String> hobbys;
private Map<String,String> card;
private Set<String> games;
public Map<String, String> getCard() {
return card;
}
public void setCard(Map<String, String> card) {
this.card = card;
}
public Set<String> getGames() {
return games;
}
public void setGames(Set<String> games) {
this.games = games;
}
public String[] getBooks() {
return books;
}
public void setBooks(String[] books) {
this.books = books;
}
public List<String> getHobbys() {
return hobbys;
}
public void setHobbys(List<String> hobbys) {
this.hobbys = hobbys;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public UserService getUserService() {
return userService;
}
public void setUserService(UserService userService) {
this.userService = userService;
}
public String Update(){
userService.update();
System.out.println("名字:"+name);
System.out.println("书籍:");
for (String book:books){
System.out.print("<<"+book+">>\t\n");
}
System.out.println("爱好:"+hobbys);
System.out.println("card:"+card);
System.out.println("games:"+games);
return "list";
}
}
GoodsAction.java
public class GoodsAction {
private UserService userService;
public UserService getUserService() {
return userService;
}
public void setUserService(UserService userService) {
this.userService = userService;
}
public String Update(){
userService.update();
return "list";
}
}
Test测试类
public class UserTest {
public static void main(String[] args) {
//加载spring核心配置文件(建模)获取spring的上下文对象
//上下文对象中可以获取任何Javabean对象
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("/Spring-Context.xml");
//用户
UserAction useraction = (UserAction) context.getBean("userAction");
useraction.Update();
System.out.println(" ===============================");
//商品
GoodsAction goodsAction= (GoodsAction) context.getBean("goodsAction");
goodsAction.Update();
}
1.Bean注入
这里的值是一个引用,ref
<bean class="com.csdn.xw.web.UserAction" id="userAction">
<property name="userService" ref="serviceImpl2"></property>
<property name="name" value="小明"></property>
</bean>
<bean class="com.csdn.xw.service.impl.UserServiceImpl2" id="serviceImpl2"></bean>
2.数组注入
<property name="books" >
<array>
<value>西游记</value>
<value>红楼梦</value>
<value>水浒传</value>
<value>三国演义</value>
</array>
</property>
3.List注入
<property name="hobbys">
<list>
<value>唱</value>
<value>跳</value>
<value>RAP</value>
</list>
</property>
4.Map注入
<property name="card">
<map>
<entry key="JAVA" value="100"></entry>
<entry key="Python" value="100"></entry>
</map>
</property>
5.Set注入
<property name="games">
<set>
<value>电脑</value>
<value>鼠标</value>
</set>
</property>
测试结果:
2.3.2.构造注入
无参构造创建对象
userAction.java
public class UserAction {
public UserAction() {
System.out.println("user创建了");
}
}
spring-context.xml
<bean class="com.csdn.xw.web.UserAction" id="UserAction"></bean>
测试结果:
有参构造创建对象
userAction.java
public class UserAction {
private String name;
private String[] books;
private List<String> hobbys;
private Map<String,String> card;
private Set<String> games;
//有参构造器
public UserAction(String name, String[] books, List<String> hobbys, Map<String, String> card, Set<String> games) {
this.name = name;
this.books = books;
this.hobbys = hobbys;
this.card = card;
this.games = games;
}
/测试有无注入
public void pros(){
System.out.println("名字:"+name);
System.out.println("书籍:");
for (String book:books){
System.out.print("<<"+book+">>\t\n");
}
System.out.println("爱好:"+hobbys);
System.out.println("card:"+card);
System.out.println("games:"+games);
}
}
spring-context.xml
<bean class="com.csdn.xw.web.UserAction" id="userAction">
<property name="userService" ref="serviceImpl2"></property>
<constructor-arg name="name" value="张三"></constructor-arg>
<constructor-arg name="books">
<array>
<value>大话数据结构</value>
<value>大话设计模式</value>
</array>
</constructor-arg>
<constructor-arg name="hobbys">
<list>
<value>沐浴</value>
<value>足疗</value>
<value>按摩</value>
</list>
</constructor-arg>
<constructor-arg name="card">
<map>
<entry key="csdn" value="nb"></entry>
</map>
</constructor-arg>
<constructor-arg name="games">
<set>
<value>Java方文山</value>
</set>
</constructor-arg>
</bean>
测试结果:
2.4.自动装配
byName(按名称自动装配)
由于在手动配置xml过程中,常常发生字母缺漏和大小写等错误,而无法对其进行检查,使得开发效率降低。采用自动装配将避免这些错误,并且使配置简单化。
测试:
1、修改bean配置,增加一个属性 autowire=“byName”
<bean class="com.csdn.xw.web.GoodsAction" id="goodsActiona" autowire="byName">
<property name="userService" ref="serviceImpl1"></property>
</bean>
<beans xmlns="http://www.springframework.org/schema/beans"
default-autowire="byName"
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">
2、再次测试,结果依旧成功输出!
3、我们将 GoodsAction的bean id修改为 goodsACtion
4、再次测试, 执行时报空指针java.lang.NullPointerException。因为按byName规则找不对应set方法,真正的setgoodsAction就没执行,对象就没有初始化,所以调用时就会报空指针错误。
小结:
当一个bean节点带有 autowire byName的属性时
或是beans节点带有 default-autowire="byName"。
-
将查找其类中所有的set方法名,例如setCat,获得将set去掉并且首字母小写的字符串,即cat。
-
去spring容器中寻找是否有此字符串名称id的对象。
-
如果有,就取出注入;如果没有,就报空指针异常。
byType (按类型自动装配)
使用autowire byType首先需要保证:同一类型的对象,在spring容器中唯一。如果不唯一,会报不唯一的异常。
NoUniqueBeanDefinitionException
测试:
1、将user的bean配置修改一下 : autowire=“byType”
2、测试,正常输出
3、在注册一个goodsAction的bean对象!
<bean class="com.csdn.xw.web.GoodsAction" id="goodsAction" autowire="byType">
</bean>
<bean class="com.csdn.xw.web.UserAction" id="userAction" autowire="byType">
<property name="userService" ref="serviceImpl2"></property>
</bean>
<bean class="com.csdn.xw.service.impl.UserServiceImpl2" id="serviceImpl2"></bean>
<bean class="com.csdn.xw.service.impl.UserServiceImpl1" id="serviceImpl1"></bean>
4、测试,报错:NoUniqueBeanDefinitionException
5、在这个配置中,我们定义了两个UserService的实现类 UserServiceImpl1和 UserServiceImpl2,并且将UserAction的autowire属性设置为byType,表示使用byType进行自动装配。
现在,如果我们运行这个程序,将会抛出一个异常,提示存在多个匹配的 bean,无法确定要注入哪个 bean。这是因为 UserAction类依赖于UserService接口,而容器中存在两个与 UserService接口匹配的 bean,即 UserServiceImpl1和 UserServiceImpl2,导致无法确定要注入哪个 bean。
这就是按照类型自动装配!
2.5.spring与web容器的整合
每一次的请求都需要进行建模,十分消耗新能,希望建模一次,然后每次的请求都可以拿到spring的上下文。使用监听器将spring上下文放入tomcat上下文中。
SpringLoadlistener.java
@WebListener
public class SpringLoadlistener implements ServletContextListener {
public void contextInitialized(ServletContextEvent sce) {
System.out.println("初始化将Spring的上下文放入tomcat");
//将Spring的上下文放入tomcat
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("/Spring-Context.xml");
//获取tomcat上下文
ServletContext servletContext = sce.getServletContext();
servletContext.setAttribute("springcontext",context);
}
}
UserServlet.java
@WebServlet("/userlist")
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//处理请求的时候获取spring上下文
ClassPathXmlApplicationContext springcontext = (ClassPathXmlApplicationContext) req.getServletContext().getAttribute("springcontext");
UserAction useraction = (UserAction) springcontext.getBean("userAction");
System.out.println(useraction);
useraction.Update();
}
}
测试结果:
到这里我的分享就结束了,欢迎到评论区探讨交流!!
如果觉得有用的话还请点个赞吧 ♥ ♥文章来源:https://www.toymoban.com/news/detail-698169.html
文章来源地址https://www.toymoban.com/news/detail-698169.html
到了这里,关于一文读懂Spring IOC从演变到自动装配的全攻略的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!