一篇有漏洞的Spring博文

前言:

 一年前这个时候我完成了自己的第一个SSM😄的项目已经过去了一个月,当时秉着会用就好的态度,从最初的项目需求到后端整个的框架设计都很顺利,得益于Spring、SpringMVC和MyBatis的便捷,代码写得很快,思路也较清楚。但在配置项目的时候,总是有很多不理解的地方,到现在也有不少的困惑。

 我觉得需要向之前的自己介绍一下Sping,一是整理一下逻辑,一是为之后更深的理解打下基础。如果你和我一样Spring的知识点有些遗忘,不妨继续看下去,我相信还是会有一点点收获的。

 文章结构如下所示,能力有限,若有不当欢迎讨论指正:
在这里插入图片描述


一、简单的MVC开发过程

 假设我们在学校需要开发一个网上书店系统,并且使用简单的JavaWeb进行开发,工具以及开发语言的选择如下:数据库MySQL+服务器Tomcat+开发语言JAVA。做完需求分析之后,设计得到了大致的UI界面以及数据库表,之后便是后端代码的开发。

 后端采用简单的MVC架构开发(Model+View+Controller)我自己的理解就是模型层面(Java类以及数据库操作),View层面就是html页面和jsp页面,而Controller层面则是负责控制页面逻辑与数据层面的交互。开发的过程首先编写Java类(类对应数据库表,类里面的属性则对应数据库表中的列属性)->编写Dao层也就是数据库操作的部分,这里我们需要写原生的JDBC(也就是加载驱动、获取连接、创建statement对象、执行SQL语句得到结果,当然你可能需要创建一个properties文件保存数据库连接的用户名和密码)->编写service层(这部分也就是你想实现的业务操作,首先定义需要实现的业务接口,然后实现创建对应的类实现这个接口),例如需要添加图书,那么创建一个Book接口,里面有一个方法是addBook(),之后再创建BookImpl实现Book接口的一个类->之后我们创建controller层代码,这里就是数据与页面交接的层面。

 假设此时管理员点击添加图书,前端页面获得此信息通过http协议传递数据放到request域中(也有其它的域,例如cookie、session),我们定义一个BookServlet,里面有一个addBook()的方法用于处理这个情况。因为我们使用Tomcat服务器,所以在前端表单跳转需要跳转到此servlet,这个过程是Tomcat容器实现的,它让我们找到对应的servlet,所以我们需要在web.xml中配置对应的以及以及,但是此时如果我们在servlet中写多个方法,Tomcat服务器是无法找到对应方法是谁,这个时候我们可以在前端表单传递的时候增加信息,例如添加action=addBook,然后我们在后端就可以利用反射得到servlet对应的类以及对应的addBook执行对应的方法。

 在addBook中我们可能会创建在service层的BookImpl对象,然后利用这个对象调用方法区操作数据库,最后在把返回的信息通过http传递到前端页面,以此一个看起来简单的MVC业务流程就结束了。

但对于稍大的项目来说,简单的MVC有着很多的弊端,例如代码量过于庞大,且难以维护。对于JDBC操作来说,后来我们有了MyBatis来简化操作,而Spring生态就会简化我们其它部分的操作。


二、Spring框架结构

 虽然不想将Spring的一些概念拿出来,但是后文描述是基于自己对于某个点的理解,如果没有总体的框架结构,可能会比较繁琐,这里给出Spring官网上的结构图,以及简单的谈谈我对其中一些模块的理解。
在这里插入图片描述
 对每个模块详细的介绍可以去看官方文档,这里只是谈谈我的简单理解。我们从上到下看看每个模块,首先是数据集成模块,里面简化了JDBC的操作,提供了对于ORM框架的支持,以及支持了transaction事务(这里的事务原本是数据库事务,Spring提供了可以代码编写(commit和rollback)或者使用注解来声明事务);Web层实现了SpringMVC(SpringMVC主要围绕DispatcherServlet来实现,也就是负责解决view层和controller层的事务);AOP面向切面编程我自己的理解就是不改变原有代码而在某处添加功能;测试模块也是很重要的,Spring测试模块支持Junit;最重要的核心容器其中Beans提供了BeanFactory也有ApplicationContext容器,提供依赖注入功能;Core提供了框架的基本组成部分以及IoC控制反转。Context建立在Beans和Core基础上,提供了创建上下文、事务传播、调度、模板引擎等功能。其中核心容器中具体的关系调用网上的图如下:
在这里插入图片描述

 但有几个很重要的特点以及原理是需要细说的,所以下面谈谈我对于AOP、IoC、DI的理解以及Beans的作用域、生命周期、与Spring容器的关系,还有几个注解的理解。


三、Spring特点及简单配置原理

1、AOP

 AOP:面向切面编程【底层就是动态代理】,指程序在运行期间动态的将某段代码切入到指定方法位置进行的编程方式。

 具体的操作步骤是:

  • 将业务逻辑组件和切面类都加入到容器中, 告诉spring哪个是切面类(@Aspect)

  • 在切面类上的每个通知方法上标注通知注解, 告诉Spring何时运行(写好切入点表达式,参照官方文档)

  • 开启基于注解的AOP模式 @EableXXXX

 当我们需要在某处打印日志,或者统计方法的执行的时间,或者需要进行数据库的事务处理的时候肯定是不想去修改该处的代码,而AOP机制就是在运行期间添加这些方法的好办法。例如需要计算testTime()的执行时间(不改变这个方法而实现此功能就使用AOP技术),首先我们创建包含计算时间戳的类Calculate(),这个类就是切面,里面的所有方法是连接点,而单独计算时间戳的testTime()方法则是切入点,我们在这个方法上加入后置通知的注解,然后加入开启AOP的注解,放到Spring容器中自动装配,之后就实现了这个功能。我们可以看到并没有改变任何代码,只是为了增强功能而添加了代码。下面引入AOP中一些术语:

img

 我们可以在xml配置文件中配置AOP,也可以使用注解帮助我们进行配置。对于两种AOP框架来说

  • AspectJ:完整的 AOP 实现框架

  • Spring AOP:非完整的 AOP 实现框架

    Spring AOP 和 AspectJ 都是 AOP 的实现框架,AspectJ 是 AOP 的完整实现,Spring AOP 则是部分实现。AspectJ 有一个很好的编程模型,包含了注解的方式,也包含了特殊语法。Spring 认为 AspectJ 的实现在 AOP 体系里面是完整的,不需要在做自己的一些实现。

2、IoC

 控制反转的就是将创建对象的控制权交给了Spring容器,Spring容器帮助你管理对象及其依赖关系。例如Car类中需要一个Engine类,一般的做法是主动的new Engine类,而IoC则是在实例化Car的时候自动注入一个Engine的类给它。

 下面的图形很好的展示了Beans加载的过程

在这里插入图片描述

 首先Spring运行时通过注解(autowear、bean或者xml配置(构造器方法注入、setter方法注入)知道需要去实例化Bean,读取Bean配置信息到Beans定义注册表中,根据注册表实例化Bean,将属性注入到对象中,将Bean实例放入到Spring容器缓存池(因为Bean的作用范围也是不同的)。

img

 给出Spring框架中bean的生命周期的说明来自(https://www.cnblogs.com/lkylin/p/12720552.html):

  • Spring容器 从XML 文件中读取bean的定义,并实例化bean。
  • Spring根据bean的定义填充所有的属性。
  • 如果bean实现了BeanNameAware 接口,Spring 传递bean 的ID 到 setBeanName方法。
  • 如果Bean 实现了 BeanFactoryAware 接口, Spring传递beanfactory 给setBeanFactory 方法。
  • 如果有任何与bean相关联的BeanPostProcessors,Spring会在postProcesserBeforeInitialization()方法内调用它们。
  • 如果bean实现IntializingBean了,调用它的afterPropertySet方法,如果bean声明了初始化方法,调用此初始化方法。
  • 如果有BeanPostProcessors 和bean 关联,这些bean的postProcessAfterInitialization() 方法将被调用。
  • 如果bean实现了 DisposableBean,它将调用destroy()方法。

 相关注解的说明:

装配注解主要有:@Autowired、@Qualifier、@Resource,它们的特点是:

1、@Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入;

2、@Autowired默认是按照类型装配注入的,如果想按照名称来转配注入,则需要结合@Qualifier一起使用;

3、@Resource注解是又J2EE提供,而@Autowired是由spring提供,故减少系统对spring的依赖建议使用@Resource的方式;如果Maven项目是1.5的JRE则需换成更高版本的。

4、@Resource和@Autowired都可以书写注解在字段或者该字段的setter方法之上

5、@Autowired 可以对成员变量、方法以及构造函数进行注释,而 @Qualifier 的注解对象是成员变量、方法入参、构造函数入参。 6、@Qualifier(“XXX”) 中的 XX是 Bean 的名称,所以 @Autowired 和 @Qualifier 结合使用时,自动注入的策略就从 byType 转变成 byName 了。

7、@Autowired 注释进行自动注入时,Spring 容器中匹配的候选 Bean 数目必须有且仅有一个,通过属性required可以设置非必要。

8、@Resource装配顺序

8.1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常

8.2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常

8.3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常

8.4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;


3、Beans

  • beanFactory:Bean工厂,对IOC容器的基本行为做了定义,即管理这些Bean(我们只关心从工厂里面得到什么产品,不关心工厂怎么生成这些产品。–工厂设计模式)
  • FatoryBean:工厂Bean,是一个Bean,作用是产生其他的Bean实例,Bean里面提供工厂方法。

 其中Bean的生命周期(来自https://blog.csdn.net/weixin_48182198/article/details/107593961):

 BeanFactory、FactoryBean和ApplicationContext的区别:

img


五、SSM项目开发过程

 依旧是上线一个网上书店,但是这次我们采用SSM架构设计(数据库MySQL+服务器Tomcat+后端框架SSM),在完成需求分析之后,我们得到数据库表和相关的UI界面,后端首先创建一个Maven项目(利用Maven可以更好的导入jar包,而不需要我们手动去下载到本地,Maven可以替我们操作,编写pom.xml文件即可)。创建MyBatis的配置文件mybatis-config.xml(在这里面编写引入对应的mapper.xml),创建整合整个Spring的文件applicationContext.xml。编写数据库对应的实体类,编写Dao层的Mapper接口,编写接口对应的mapper.xml文件(这里编写对应的sql语句),之后和之前一下编写Service层接口和实现类。

 之后配置Spring去整合MyBatis的相关配置文件spring-dao.xml(这里面我们关联数据库文件properties,配置数据库连接池,配置SqlSessionFactory对象(这里注入数据库连接池,配置mybatis-config.xml配置文件)),然后将Dao接口注入到Spring容器中。之后整合Service层,扫描包将service实现类注入Spring容器,配置事务管理器。

 之后就是去配置SpringMVC层,在web.xml中配置DispacherServlet,加载applicationContext.xml配置文件,设置Session过期时间等。创建spring-mvc.xml,在里面开启 。之后将spring-dao.xml、spring-service.xml和spring-mvc.xml都加载到applicationContext.xml中。配置完成之后,我们在controller层编写代码,通过模型(request等)跳转相关页面和得到相关的数据。


总结

 学习中总会觉得项目开发不断的优化,但是还是要懂得为什么这么做,以及实现的原理。之后会尝试回顾MyBatis和Maven,我们也发现SSM项目开发进行配置也较为繁琐,所以后面也会更新SpringBoot的学习。

 文中若有不当,欢迎指正,谢谢😂~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

threecat.up

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值