为什么用Spring

为什么用Spring

  • 代码复用

  • 解除耦合

Spring 是java web 开发中广泛使用的一个东西,我们用它肯定是有原因的,很多初学者在学Spring的时候不知道为什么用spring,用Spring有哪些好处,不知道为什么要学它,我简单介绍一下它的主要作用。

Spring 是一个Java框架,不是组件,相信大多数学spring的同学大多用过tomcat了,那他们两个学起来又有什么不同呢?

Tomcat

Tomcat 是web容器,你把写好的java 代码打成war包扔给他,他就会帮你运行,他帮你自动监听本地端口,解析浏览器发来的 http 请求,解析url,找到url对应的函数,然后执行这个函数,再返回给浏览器。可以说他是一个组件。

Spring

而 Spring 是一个框架,框架的意思是,套路我告诉你,你这么写就可以了,剩下的部分框架帮你做。那 Spring 帮我们做了哪些事情呢?

引入 Spring

我们在讲他的作用的时候先来看一下最最最原始的操作数据库的代码,以下面的伪代码为例,从他的演变过程来看,为什么要用Spring。

面向函数(过程)的方式

添加 jdbc 连接驱动 jar包,这里省略关闭、处理异常等…

public class Demo1 {
    static final String DB_URL = "jdbc:mysql://localhost:3306/databaseweb";
    static final String USER = "root";
    static final String PASS = "1234";

    public static void main(String[] args) throws Exception{
       Connection conn = null;
       Statement stat = null;
       Class.forName("com.mysql.jdbc.Driver");
       conn = (Connection) DriverManager.getConnection(DB_URL,USER,PASS);
       
       // 执行查询
       stat = conn.createStatement();
       String sql = "SELECT * FROM tb_person";
       ResultSet rs = stat.executeQuery(sql);
       // 输出查询结果
       while(rs.next()){
           System.out.print(rs.getInt("id")+",");
           System.out.print(rs.getString("name")+",");
           System.out.print(rs.getString("sex")+",");
           System.out.print(rs.getInt("age"));
           System.out.print("\n");
       }
       // 省略关闭连接.....
}

(以上部分代码转自网络)
这样写,一气呵成,真爽,一个类就完成了,而这时面向函数式编程,java是面对对象的
(为什么要面对对象?是因为方便开发、维护等…)


封装成工具类

可能有人觉得这样写没问题,挺好的,我也觉得这样写完全没毛病,因为可能他只需要查看一下这个表。
但是我们在开发一个web项目时,有好多张表,好多次增删改查,如果每次都这么写,那岂不是得累死?没错,所以我们就有了以下改进:

  • 写了一个JDBCUtil 工具类,我们需要建立连接的时候直接 JDBCUtil.getConnection(); 调用工具类的方法即可

JDBCUtil

public class JdbcUtil {
	private static String url = "jdbc:mysql://localhost:3306/jdbcDB?useSSL=true";
	private static String username = "root";
	private static String password = "root";
	private JdbcUtil(){}
	public static Connection getConn() throws SQLException{
		return DriverManager.getConnection(url,username,password);
	}
}

Demo2

public class Demo1 {
    public static void main(String[] args) throws Exception{
    try{
       Connection conn = JDBCUtil.getConnection();
       Statement stat = conn.createStatement();
       String sql = "SELECT * FROM tb_person";
       ResultSet rs = stat.executeQuery(sql);
       // 输出查询结果
       while(rs.next()){
           System.out.print(rs.getInt("id")+",");
           System.out.print(rs.getString("name")+",");
           System.out.print(rs.getString("sex")+",");
           System.out.print(rs.getInt("age"));
           System.out.print("\n");
       }
       conn.close();
}

这样是不是舒服了很多?以后写起代码来只需要 getConn() 就行了.


解除数据库和代码的耦合

有一天我发现我的数据库列名起的不合适,name 需要改成 nickName,我们这时发现,数据库列名一改,代码中所有用到这一列的地方( rs.getString(“name”))都要改 ,代码多了还找不到哪里要改,想想都可怕。

  • 于是我们新建了一个 User 类,这样,便松了代码和数据库列名的强耦合关系,以后数据库列名变化,我们只需要改一个地方就行了。
    User.java
class User(){
	int id;
	String name;
	//省略其他属性....
	public String getName(){
		return name;
	}
	public void setName(String name){
		this.name = name;
	}
	//省略其他get set..
	public String toString(){
		//省略...
	}
}

UserDataAccessObject.java

//将 ResultSet 转化成 User 实体类
public UserDataAccessObject{
	public static User toUer(ResultSet rs){
		User user = new User();
		user.setId(rs.getInt("id"));
		user.setName(rs.getString("name"));
		//其他属性...
		return user;
	}
	//省略增删改
}

Demo3

Connection conn = JDBCUtil.getConnection();
Statement stat = conn.createStatement();
String sql = "SELECT * FROM tb_person";
ResultSet rs = stat.executeQuery(sql);
User user = UserDataAccessObject.toUser(rs);
System.out.println(user);
conn.close();

这样我们使用的时候只需要 DBResultHandleUtil.toUser(rs); 就自动将结果集转为 User 了,以后数据库改动的时候,只需要改 UserDataAccessObject 就可以了,写着写着,发现UserDataAccessObject名字太长,以后就简写成了 UserDAO


解耦逻辑和连接

之前我们查询的时候只是查询所有用户,随着我们的业务量增加,来了新的需求,只推广我们的儿童产品给有购买能力的成人用户,因此我们需要查询 age > 18 的,按照之前的方式是放在 UserDAO 里面进行的,

  • 因此程序猿又要改 UserDataAccessObject 的sql,加上where age > 18
  • 加完后,公司又说我们需求变了,还是推广给所有用户吧,因为孩子看到会和父母说
  • 程序猿又将sql改回来
  • 刚改完,公司又说,这个不能让孩子看到,还是只推荐给父母吧
  • 循环…
  • 程序猿怨言不断,我刚改完,又特么要改回来,擦,烦死了。
  • 于是比较懒惰的程序猿想到了将业务逻辑 和 数据库连接相关 拆成两个部分。
    UserDAO.java
class UserDAO{
	public static List<User> query(String sql){
		//...
	}
}

UserService.java

class UserService{
	List<User> queryAll(){
		String sql = "select * from user";
		return UserDAO.userDao.query(sql);
	}
	List<User> queryAdult(){
		String sql = "select * from user where age > 18";
		return UserDAO.userDao.query(sql);
	}
}

现在管你什么需求,新的来了,我只需要在 UserService 添加新的方法就行了,你要是想改回来,那我就把调用的地方改回原来的函数就行,我真机智,爽~


接口隔离

  • 用mysql用的好好的,有一天,公司经理说,MySQL我们不用了,现在用orcle,而且我们的DAO 层代码要改,别用query了,以后统一改成find开头
  • 然后DAO层不用了,换成了UserOrcleDAO,UserService中所有调用 UserDAO的地方都要改,程序猿说这简单,就是麻烦,然后改了
  • 然后公司又说,orcle 不好用,还是用 mysql 吧
  • 程序猿改之。
  • 刚改完了公司又说,不行,orcle更好,用orcle
  • 程序猿苦不堪言,一边改一边心里默默问候他全家
  • …循环
  • 有程序猿想,你要是再这么改下去,那我岂不是要原地爆炸?
  • 于是刚买了U盘的程序猿想,我A牌子U盘和B牌子U盘都能插我电脑正常用,我换U盘 电脑插口就不用换,为什么呢?因为他们都实现了 USB 的接口,聪明的他想出了用接口隔离 DAO 的变化

UserDAO.java

interface UserDAO{
	List<User> findAll(String sql);
}

UserDAOImplForMysql.java

class UserDAOImplForMysql implements UserDAO{
	public List<User> findAll(String sql){
		//...
	}
}

UserService.java

class UserService{
	UserDAO userDao = new UserDAOImplForMysql(); //依赖实际的实现类
	List<User> queryAll(){
		String sql = "select * from user";
		return userDao.findAll.query(sql);
	}
	List<User> queryAdult(){
		String sql = "select * from user where age > 18";
		return userDao.userDao.findAll(sql);
	}
}

程序猿想,这样你再变,我只需要改一下 new 所在位置改为 UserDAOImplForOrcle 就行了,哼,休想让我加班!

Spring 到来

  • 虽然程序猿已经大大减少了修改时,返工花费的时间,也提高了代码的复用性,可是日积月累,Service类个数不断增加,越来越多的类出现,已经难以维护时,程序猿在需求频繁的寒冬里瑟瑟发抖。
  • 这时候,有个懒懒的程序猿受不了了,大喊:我特么改够了!
  • 随后他收集原因:使用任何语言的原生方式,尽管使用接口隔离变化,但永远避免不了强依赖,于是他就想让计算机帮我们管理这些类的依赖关系,于是 Spring 诞生了

Spring是管理 java 类( 又称 java bea) 的容器,他把类之间的耦合关系的管理权限从程序猿交给计算机去做,这称之为 IOC (inverse of control 控制反转),他的思想是将自己写好的类,放入 Spring 的 Bean容器中,放入方式有多种,称之为 DI (Dependency Injection,依赖注入),可以选择依赖的方式,比如按照类型,按照类名称等。

IOC 和 DI 是 Spring 的两大特性,也是spring的核心思想。

Spring 一词翻译为春天,他的到来寓意程序猿将真正的从寒冬中走出,迎来春天。

Spring 的使用

Spring 的使用方式有配置文件和注解两种。下面简单介绍,以注解的使用时候和上面不适用 Spring 的区别:
还是上面的代码
省略在配置文件中开启自动扫描包

UserDAOImplForMysql.java

//添加 @Bean 注解,让spring 知道这个类允许他接管
@Bean
class UserDAOImplForMysql implements UserDAO{
	public List<User> findAll(String sql){
		//...
	}
}

UserService.java

@Component
class UserService{
	//不再需要new了,只需要添加注解,Spring自动帮我们选择对应的 bean
	//UserDAO userDao = new UserDAOImplForMysql(); //依赖实际的实现类
	
	@Autowirte
	UserDAO userDao; //使用一个注解就可以让 spring 自动帮我们注入对应的 bean
	
	List<User> queryAll(){
		String sql = "select * from user";
		return userDao.findAll.query(sql);
	}
	List<User> queryAdult(){
		String sql = "select * from user where age > 18";
		return userDao.userDao.findAll(sql);
	}
}

使用spring 后,类间的耦合关系消除了很多很多,春天(Spring)来了,尽情在春天(Spring)中自由徜徉把~


本文仅为 Spring 思想初探,不足以作为入门等,更多相关细节和知识,大家可以自行了解。

  • Spring 是怎么实现Bean容器
  • IOC 和 DI 原理等
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值