三大框架:业务层框架Spring+IoC+DI

往期文章:jsp与cookie、重定向与RESTFul架构支持

下一章节: 持久层框架MyBatis


初识Spring框架

MyBatis 入门https://www.w3cschool.cn/mybatis/mybatis-dyr53b5w.html

1.解决什么问题

业务层:主要处理业务逻辑,需要对象,以前是自己new对象,管理对象,可以吧对象放在list或map中。

2.是什么?

是业务层框架,主要有两个功能
2.1 是ioc容器,ioc容器他提供了一个hashMap(提供了一个容器来存放对象)
IOC: Inversion of Control(控制反转)
控制反转:将对象的创建权反转给(交给)Spring

DI:依赖注入,在Spring框架负责创建Bean对象时,动态的将依赖对象注入到Bean组件中!!
理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:
●谁依赖于谁:当然是应用程序依赖于IoC容器;
●为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源;
●谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象;
●注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。
DI和IOC的关系: DI不能单独存在,DI需要在IOC的基础上来完成.

这样做得好处:做到了单一职责,并且提高了复用性,解耦了之后,任你如何实现,使用接口的引用调用的方法,永远不需要改变


2.2 aop功能,动态代理(静态代理详解https://www.cnblogs.com/whirly/p/10154887.html)由程序员创建或特定工具自动生成源代码,也就是在编译时就已经将接口,被代理类,代理类等确定下来。

3.如何使用?

3.1 通过xml配置方式使用(更加麻烦)
3.2 创建springboot项目,内置了spring(代码量少,新手入门建议学spring这种方法)

注册时在业务层判断用户名是否存在。
获取商品价格时,判断用户是否是会员,商品有没有参加店铺活动,有没有参加商城活动。

Spring的野心

springMVC作为WEB框架深受企业爱戴,它会自己管理Controller,来创建其实例。Mybatis作为持久层优秀的框架,它也自己管理持久对象。可以看到,各个诸侯都自己管理对象,而要想让它们对象复用,那真是繁琐。
如何破局呢?要想发号施令其它人听,最好的解决办法就是扼住他们的咽喉。在java的世界里最重要的无疑就是对象的生命周期管理。于是spring以此为切入点,实现自己的统治。宣布所有对象由我来管理,springMVC你不再管理对象,由我来管理,你要用从我这拿。Mybatis你也不再管理对象,由我来管理,你要用从我这拿。你说管就管吗?这两个征战数年战功赫赫的大将军会听一个初出茅庐乳臭未干野小子的话?他们当然不会听,spring的话可以不听,但他们都要听开发者的。开发一个完整的系统有四个核心,WEB层支持、业务逻辑层、持久层支持、事务支持。而这就是它们的软肋,这就是它们的命门所在,它们只能完成一部分工作,不是一个整体解决方案。而spring并没有抹杀它们,而是依然高官厚禄,承认它们的市场地位,还赠与一个事务管理。一边打压一边拉拢,它们两位看看大势已去,只能俯首称臣。于是兵不血刃,一场变革悄然兴起,一个经典的三层框架诞生SSM (SpringMVC+Spring+Mybatis)。
故事很传奇,听的人很开心。可spring真就这么简单吗?如果这样想,你就大错特错了。例如:spring怎么来实现对象的管辖?怎么让不同技术之间能简单的互相配合?这才是spring的决胜之处。
为实现这些spring是煞费苦心,创新的形成了一套新的理论体系,可谓前无古人后无来者。其中最核心的是:IoC控制反转、DI依赖注入、SpringAOP面向切面编程、事务控制。

框架组成

Spring官网: http://spring.io
Spring是一个开源框架,是为了解决企业应用程序开发复杂性而创建的。Spring框架的不光是技术牛,而是它的核心思想更牛,它不重复发明轮子,而是“拿来主义”,把业界做的最好的技术黏合起来形成一个强大的企业级的应用框架。

用springboot方式实现ioc

需求

1.拷贝webdemo倒工作区,直接把文件夹改名为spring01ioc,修改pom.xml中的antifactid和name,eclipse -->maven -->existing maven projects

导入eclipse

修改为pom.xml中的antifactid和name



2.在主包下面创建controller,创建UserController

@autowired spring框架会从ioc容器中取一个对象赋值给userService UserService userService

3.创建业务层Service

interface UserService{register}

@Service 与controller功能类似,由spring创建UserServicelmpl类对象
对象存放在spring框架中的ioc容器(hashMap)
class UserServicelmpl implements UserService

步骤1:创建接口

package com.tedu.webDemo.service;public interface UserService {public int register(String username);
}
步骤2:创建一个接口的实现类

package com.tedu.webDemo.service;import org.springframework.stereotype.Service;//接口的实现类
@Service //告诉spring框架为类创建一个对象
//对象放在spring框架的ioc容器(hashMap)中
public class UserServiceImp1 implements UserService{//返回类型最好用包装类型integer@Overridepublic int register(String username) {//控制层springmvc调用业务层//判断用户名是否存在//调用数据库层mybatisreturn 0;}
}

创建控制层

步骤3:创建控制层
package com.tedu.webDemo.controller;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import com.tedu.webDemo.service.UserService;
import com.tedu.webDemo.service.UserServiceImp1;//创建控制层
@RestController
public class UserController {//以前//UserController依赖UserServiceImp1//UserController被UserServiceImp1控制UserServiceImp1 UserServiceImp1=new UserServiceImp1();//控制层调用业务层,对象是从ioc容器中取//对象的类型要写接口,不要写具体的实现类的类型//对象从spring框架中来//被框架控制//控制反转ioc inversion of controller@AutowiredUserService userService;@RequestMapping("/reg")//在控制层,业务层方法的第一行加断点//main() Debug AS//console 是否显示tomcat started on port 8080//localhost:8080/register F6,F8public String register(String username) {int state=userService.register(username);return "state="+state;}
}

class UserServicelmpl2
以前创建对象把这个写死了 UserServicelmpl userServicelmpl = new UserServicelmpl()
创建对象时把对象改为接口 UserService userService = new UserServicelmpl2();

小结

这就是spring框架的IoC,控制反转。之前我们自己new出新类。new UserService(),现在由容器提供。
在java范畴中万物皆Object,在Spring中万物皆Bean。Bean是Spring的核心、基础、根源。
上面的方式很多同学会觉得不以为然,感觉还没有我们传统方式实现方便呢,new个对象不就可以了。凭空多个什么IoC,什么DI乱七八糟的感觉。是那样吗?不光大家这样觉得,业界开始时也对它嗤之以鼻,但随着Spring3.0的推出,随着注解方式的成为市场主流编程方式,它的力量开始展现,让我们这些俗人开始仰慕!这其中也包括我。
要不断的去适应ioc方式



生命周期:

查看步骤三 控制层
对象什么时候创建,什么时候被回收?
controller默认是系统启动时创建,系统关闭时回收
@scope(“singleton”)单例,只创建一个对象
@scope(" ")

http://localhost:8080/reg?username=a
debug跟踪流程

Singleton,prototype,session

scope:singleton单例,每次得到的对象是一样的
prototype: 每次得到的对象是个新的

分析

AccessCount应该只有一个
LogInfo是每次创建新的
UserCart是一个用户创建一个

需求

需求:网站上来一个用户加1,放在accessCount
用户购物车:userCart
日志:logInfo

实现

@component的功能与@service类似,加了@component后框架会创建对象,@service表示创建的是业务层对象,@component表示创建的是普通对象。

在com.tedu.webDemo.service包中创建三个类AccessCount、LogInfo、UserCart

AccessCount类

package com.tedu.webDemo.service;import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;//组件:由框架管理的类
@Component //@Component是组件
//@controller,@restControler,@service都是组件
//@controller,@restControler,是专门用来接收数据
//@service类是专门处理数据的,是业务层的类@Scope("singleton")
//单例,服务器启动时创建,关闭时 被回收
public class AccessCount {}

LogInfo

package com.tedu.webDemo.service;import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;//处理日志,记录每次访问的时间
@Component
@Scope("prototype")//每次通过@autowired拿对象,都会创建一个新的
public class LogInfo {}

UserCart

package com.tedu.webDemo.service;import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;//购物车 (浏览器打开的时候创建)
@Component
@Scope("session")//第一次访问时创建
//关闭浏览器,对象被回收
public class UserCart {}

修改:UserController 控制层

package com.tedu.webDemo.controller;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import com.tedu.webDemo.service.AccessCount;
import com.tedu.webDemo.service.LogInfo;
import com.tedu.webDemo.service.UserCart;
import com.tedu.webDemo.service.UserService;
import com.tedu.webDemo.service.UserServiceImp1;//创建控制层
@RestController
@Scope("prototype")
public class UserController {//以前//UserController依赖UserServiceImp1//UserController被UserServiceImp1控制UserServiceImp1 UserServiceImp1=new UserServiceImp1();//控制层调用业务层,对象是从ioc容器中取//对象的类型要写接口,不要写具体的实现类的类型//对象从spring框架中来//被框架控制//控制反转ioc inversion of controller@AutowiredUserService userService;//从是spring框架的ioc容器中取对象@AutowiredAccessCount accessCount;@AutowiredLogInfo logInfo;@AutowiredUserCart userCart;//测试商品对象@RequestMapping("/test")public String test() {return accessCount.toString()+"<br>"+logInfo.toString()+"<br>"+userCart.toString();}@RequestMapping("/reg")//在控制层,业务层方法的第一行加断点//main() Debug AS//console 是否显示tomcat started on port 8080//localhost:8080/register F6,F8public String register(String username) {int state=userService.register(username);return "state="+state+this.toString();}
}

http://localhost:8080/test
Debug AS执行

业务层有多个实现类

案例:生活中假如你女朋友是双胞胎,姐妹两长的一样,你会到家你发现,你女朋友 姐妹两人都在,这个时候你应该怎么去区分?
spring框架到ioc容器中找到所有的对象判断这个对象的类型,如果是UserService就赋值
@autowired
UserService userSerivce

interface UserService
class UserServicelmpl

@service
class UserServiceImpl2 implements UserService

自动装配类型

在service包中再创建一个UserServiceImpl2 类

package com.tedu.webDemo.service;import org.springframework.stereotype.Service;@Service//spring框架会自动为类创建对象
//对象放在ioc容器中
public class UserServiceImpl2 implements UserService {public int register(String username) {return 0;}
}

创建两个业务层实现类,默认会出错

http://localhost:8080/reg

默认是根据类型找对象
根据类型找不到对象,再根据名字找对象

package com.tedu.webDemo.service;import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;//处理日志,记录每次访问的时间
@Component
@Scope("prototype")//每次通过@autowired拿对象,都会创建一个新的
//用完就回收
public class LogInfo {}

```java
package com.tedu.webDemo.service;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;//接口的实现类
@Service //告诉spring框架为类创建一个对象
//对象放在spring框架的ioc容器(hashMap)中
//框架创建对象时,对象放在hashMap中,key是userServiceImpl
public class UserServiceImpl implements UserService{
//返回类型最好用包装类型integer@Overridepublic int register(String username) {//控制层springmvc调用业务层//判断用户名是否存在//调用数据库层mybatisreturn 0;}
}
package com.tedu.webDemo.service;import org.springframework.stereotype.Service;@Service//spring框架会自动为类创建对象
//对象放在ioc容器中,key是userServiceImpl2
public class UserServiceImpl2 implements UserService {@Overridepublic int register(String username) {return 0;}
}
package com.tedu.webDemo.controller;import javax.websocket.Decoder.TextStream;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import com.tedu.webDemo.service.AccessCount;
import com.tedu.webDemo.service.LogInfo;
import com.tedu.webDemo.service.UserCart;
import com.tedu.webDemo.service.UserService;
import com.tedu.webDemo.service.UserServiceImpl;//控制层
@RestController
@Scope("prototype")
public class UserController {//以前//UserController依赖UserServiceImpl//UserController被UserServiceImpl控制//UserServiceImpl UserServiceImpl=new UserServiceImpl();//控制层调用业务层,对象是从ioc容器中取//对象的类型要写接口,不要写具体的实现类的类型//对象从spring框架中来//被spring框架控制,依赖框架//控制反转 ioc inversion of controller@Autowired//默认是根据类型赋值//如果框架有2个对象的类型是UserService,赋值失败//先根据类型赋值,失败后,再根据对象的名称赋值//userServiceImpl,对象//userServiceImpl2,对象UserService userServiceImpl;@AutowiredUserService userServiceImpl2;@Autowired@Qualifier("userServiceImpl2")//框架hashmap.get(userServiceImpl2),能取到对象//对象赋值给userService//先根据类型找到2个对象,赋值失败UserService userService;@RequestMapping("/test2")public String test2() {return userServiceImpl.toString()+"<br>"+userServiceImpl2.toString()+"<br>"+userService.toString();}//从spring框架的ioc容器中取对象@AutowiredAccessCount accessCount;@AutowiredLogInfo logInfo;@AutowiredUserCart userCart;@RequestMapping("/test")public String test() {return accessCount.toString()+"<br>"+logInfo.toString()+"<br>"+userCart.toString();}@RequestMapping("/reg")//在控制层,业务层方法的第一行加断点//main() debug as //console 是否显示 tomcat started on port 8080//localhost:8080/register  F6,F8public String register(String username) {int state=userServiceImpl.register(username);return "state="+state+this.toString();}
}
package com.tedu.webDemo;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class WebDemoApplication {public static void main(String[] args) {SpringApplication.run(WebDemoApplication.class, args);}
}

Run as执行:

三大框架之spring框架+IoC控制反转、DI依赖注入相关推荐

  1. IOC控制反转(依赖注入思想)

    IOC控制反转(依赖注入思想) 获取map 类型的 request session application 的方法: 实现RequestAware,SessionAware,ApplicationAw ...

  2. java json injection_Java Web实现IOC控制反转之依赖注入

    控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的Spring框架的核心. 控制反转一般分为两种类型,依赖注入 ...

  3. 轻松了解Spring中的控制反转和依赖注入

    点击上方 "程序员小乐"关注公众号, 星标或置顶一起成长 每天早上8点20分, 第一时间与你相约 每日英文 When you have something you really l ...

  4. Spring容器,控制反转,依赖注入

    Spring boot学习之旅,为更好督促自己学习以记之,仅供参考. spring容器 程序启动的时候会创建spring容器,扫描给spring容器一个清单,比如:@Controller, @Bean ...

  5. spring中的控制反转和依赖注入之间的关系

    Spring中的控制反转:把new这一个过程交给了spring容器去处理. 控制反转就是将new对象这一个过程交给外部去做(即Spring)而不是自己去创建. 图中的1"控制正转" ...

  6. 详解spring的IOC控制反转和DI依赖注入

    转载 详解spring的IOC控制反转和DI依赖注入 2018-06-05 15:45:34 jiuqijack 阅读数 2945 文章标签: spring IOC控制反转 DI依赖注入 更多 分类专 ...

  7. Java之控制反转和依赖注入

    1.简介 依赖注入和控制反转,目的是为了使类与类之间解耦合,提高系统的可扩展性和可维护性,下面通过一个例子来引入这一概念. 2.案例 1)一般情况下的类耦合 Main.java public clas ...

  8. Spring框架中的控制反转和依赖注入

    控制反转: 控制反转是用来降低代码之间的耦合度的,基本思想就是借助"第三方"实现具有依赖对象的解耦. 为什么需要控制反转,因为项目中对象或多或少存在耦合.控制反转的关键在于Ioc容 ...

  9. SSM框架—Spring基础—控制反转和依赖注入(概念)

    控制反转: 控制反转(IoC)是面向对象编程的一个设计原则,用于降低代码耦合度 在传统面向对象编程中,获取对象的方式是用关键字"new"主动创建一个对象,也就是说,应用程序掌握着对 ...

  10. Spring之IOC~控制反转

    1.Spring概述 1.1.什么是Spring Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One- ...

最新文章

  1. Java相对路径/绝对路径总结(转)
  2. hdfs深入:10、hdfs的javaAPI操作
  3. 五一重装WinXP操作系统所遇问题的解决
  4. IDEA提交项目到SVN
  5. 国内各大平台的推荐算法,看到360的时候笑喷了……
  6. mysql连接查询(内联)_MySQL之连接查询
  7. mysql 自定义函数教程_MySQL自定义函数
  8. C # 操作 XML
  9. JDBC在Java Web中的应用——分页查询
  10. Win10家庭中文版( 连接远程桌面要求的函数不受支持、这可能是由于 CredSSP 加密 Oracle 修正 )
  11. 怎样把计算机设置到小米手机桌面上,小米自由桌面如何设置和使用【图文教程】...
  12. 【VMCloud云平台】SCAP(四)连接公有云(二)
  13. 利用pandas拆分单元格并进行分组聚合
  14. 《后端》开放平台API安全设计
  15. 解决每次运行终端,自动激活conda环境问题
  16. luogu P4363 [九省联考2018]一双木棋chess
  17. 0120 C指针跳转、数组名指向(笔记)
  18. 使用STC15系列单片机操作sht30
  19. INTEL G41时序
  20. [英语歌曲]带我去月球:Fly me to the moon

热门文章

  1. html中显示js获取的图片地址,js如何获取UEditor富文本编辑器中的图片地址
  2. 静态HTML网页设计作品商城网站设计——蘑菇街商城(1页) HTML+CSS+JavaScript web前端课程设计_web前端课程设计代码,web课程设计-HTML网页制作代码
  3. java编程要求算法吗_JAVA编程
  4. 用计算机求函数总分 平均分,08年计算机一级辅导:Excel中用SUMIF函数实现按指定条件求平均值...
  5. [UE4]使用材质将图片变成黑白
  6. 2019华东师大考研实录 初试+复试(计专) 3个月考上985
  7. 异常Error和Exception
  8. 关于JS中addEventListener的使用
  9. Charles设置手机拦截
  10. 转: 写给想成为前端工程师的同学们 (from 360前端团队)