2023-12-22
1、Java原生开发存在问题
1.1、DAO层存在问题

1)每次都要做大量的相同的操作
2)对执行sql语句过程中所出现的各种异常和资源释放进行处理
3)需要更多的代码来提取结果并将它们映射到对象实例中
1.2、Service层存在问题

1)当功能越来越多, 与业务逻辑无关, 但是被多处业务逻辑模块共享的代码
(比如判断用户登录, 日志管理, 权限检查, 事务管理等)
的修改和维护的成本大大增加。

2)没有做到资源复用,创建了许多重复对象。
造成大量资源浪费*
3)更换实现类需要改动多个地方。
修改和维护的成本大大增加。
参考CSDN博主「灵魂相契的树」的原创文章,原文链接:https://blog.csdn.net/yzhcjl_/article/details/132520053
参考知乎作者「码农出击」的原创文章,原文链接:https://zhuanlan.zhihu.com/p/493973685
1.3、Controller层存在问题

1)每个servlet处理特定的请求,如果servlet过多,会导致在web.xml内容过多(web.xml文件方式配置)、servlet类文件数量过多。
2)通常使用JSP进行页面展示,对前端不是特别友好。
3)servlet具有容器依赖性,必须放在服务器中运行,不利于单元测试。
JSP 页面无法直接访问需要有 Java Servlet 容器来编译和运行
2、解决方案

SpringMVC:
1)
2)
Spring:
1)Spring IOC有许多优点,它可以帮助改善代码的结构、可维护性和可测试性。
低耦合——代码分离、便于代码复用
2)Spring AOP能帮助我们无耦合的实现日志记录,性能统计,安全控制等。
高内聚——结构清晰、便于开发维护
Mybatis:
1)避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。resultType自动映射查询结果,resultMap复杂场景下构建一个结果映射
参考CSDN博主「向上爬的小蜗牛」的原创文章,原文链接:https://blog.csdn.net/LyySwx/article/details/90900013
3、Spring
3.1、IOC
IoC(inversion of control):把对象的创建、赋值、管理工作都交给代码之外的容器实现,即对象的创建是由其他外部资源完成。
相关概念
1)控制:创建对象,对象的属性赋值,对象之间的关系管理。
2)反转:把原来的开发人员管理、创建对象的权限转移给代码之外的容器实现。由容器代替开发人员管理对象、创建对象、给属性赋值。
3)正转:由开发人员在代码中,使用new构造方法创建对象等,开发人员主动管理对象。
/*
示例:
Spring IoC 容器创建好 B 的实例对象后并赋值给 A 对象中的 b 属性(成员变量)的过程,就是所谓的「依赖注入
*/
public class A {
private B b;
// 省略 getter 和 setter
// 省略构造方法
}
IoC的技术实现:
DI (Dependency Injection,依赖注入):是IoC 的一种具体实现方式,它是指将对象所依赖的其他对象(即依赖)通过构造函数、Setter 方法或其他方式注入到对象中,从而消除了对象之间的耦合关系。
只需要在程序中提供要使用的对象名称就可以,至于对象如何在容器中创建、赋值、查找都由容器内部实现
3.1.1、依赖注入的方式
1)基于构造方法的依赖注入
构造方法的优势: 保证一些必要的属性在Bean实例化时就得到设置,并且确保了Bean实例在实例化后就可以使用。
构造方法的弊端: 在创建对象时,如果用不到这些数据,也必须提供。
标签:<constructor-arg></constructor-arg>
属性:
type:用于指定要注入的数据类型,该数据类型也是构造函数中的某些类型或者某些参数
index:指定要注入的数据给构造函数中指定索引位置的参数赋值,参数索引的位置从0开始
name:用于指定构造函数中指定名称的参数赋值(常用)
(以上三个标签根据需要选一个就行)
一一一一一一一一一一一一一一一一一
value:用于提供基本类型和String类型的数据
ref:用于指定其他Bean类型的数据,需填写在SpringIOC容器中的唯一id
- Dao类
//基于构造方法注入
public class UserDao {
private String name;
private int age;
public UserDao(String name, int age) {
this.name = name;
this.age = age;
}
public void insert(){
System.out.println("保存用户:"+age+"岁"+name);
}
}
- Service类
//基于构造方法注入
public class UserService {
private UserDao userDao;
public UserService(UserDao userDao) {
this.userDao = userDao;
}
public void add(){
userDao.insert();
}
}
-
XML配置文件
Ⅰ、按名称匹配入参
<!--按名称匹配入参-->
<bean id="userDao" class="org.example.dao.UserDao">
<constructor-arg name="name" value="李四"></constructor-arg>
<constructor-arg name="age" value="55"></constructor-arg>
</bean>
<bean id="userService" class="org.example.service.UserService">
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>
Ⅱ、按类型匹配入参
<!--按类型匹配入参-->
<bean id="userDao" class="org.example.dao.UserDao">
<constructor-arg type="java.lang.String" value="李四"></constructor-arg>
<constructor-arg type="int" value="55"></constructor-arg>
</bean>
<bean id="userService" class="org.example.service.UserService">
<constructor-arg type="org.example.dao.UserDao" ref="userDao"></constructor-arg>
</bean>
Ⅲ、按索引匹配入参
<!--按索引匹配入参-->
<bean id="userDao" class="org.example.dao.UserDao">
<constructor-arg index="0" value="李四"></constructor-arg>
<constructor-arg index="1" value="55"></constructor-arg>
</bean>
<bean id="userService" class="org.example.service.UserService">
<constructor-arg index="0" ref="userDao"></constructor-arg>
</bean>
Ⅳ、联合使用类型和索引匹配入参(适用于有多个构造函数,根据索引入参无法匹配的情况)
<!--联合使用类型和索引匹配入参-->
<bean id="userDao" class="org.example.dao.UserDao">
<constructor-arg index="0" type="java.lang.String" value="李四"></constructor-arg>
<constructor-arg index="1" type="int" value="55"></constructor-arg>
</bean>
<bean id="userService" class="org.example.service.UserService">
<constructor-arg index="0" type="org.example.dao.UserDao" ref="userDao"></constructor-arg>
</bean>
- 测试类