Java-SpringBoot-使用多态给项目解耦
提及
今天在打算维护一下智慧社区这个项目的时候,想到项目是使用Satoken这个开箱即用的授权和认证的组件,因为在项目开启的时候对SpringSecurity并不熟悉,而Satoken类似傻瓜式的,导入依赖进去,配置一下获取权限和角色的方法即可使用。
但是由此带来的问题就是,项目中充斥着Satoken的API方法,类似于StpUtil.isLogin(),StpUtil.getLoginIdAsLong()这类方法在Service层中已经是相当常见了,尽管是非常的方便,但是带来的问题就是假如后面我要替换另外一款权限认证和授权的组件,那么这些API方法通通都需要进行修改,这种强耦合很明显是不合理的。
我突然想到在SpringSecurity中,配置密码加密方法的时候,我们可以选择任意的密码加密方法。
@Beanpublic PasswordEncoder getPasswordEncoder() { return new BCryptPasswordEncoder();}
那么,我能不能也像这样子,提供一个统一的接口,通过选择实现方式的不同,从而达到当需要更换别的实现方式的时候,只需要更改该处代码即可。
多态
其实这需要利用到Java的三大特性之一,多态。Java的三大特性分别是封装,继承和多态。
这里使用一个小例子来演示一下什么是多态。
我们先创建一个接口,这个接口只需要含有我们统一所需的方法。
/** * @Author: Alickx * @Date: 2022/06/12/16:22 * @Description: 统一接口 */public interface IRun { /** * 跑步 */ void run();}
然后我们需要来创建几个实现该接口的实现类
分别是Man.java和Woman.java
/** * @Author: Alickx * @Date: 2022/06/12/16:27 * @Description: 男人的实现类 */public class Man implements IRun{ @Override public void run() { System.out.println("我是Man,我在run"); }}
/** * @Author: Alickx * @Date: 2022/06/12/16:27 * @Description: 女人的实现类 */public class Woman implements IRun{ @Override public void run() { System.out.println("我是Woman,我在run"); }}
接着上面的提及,我们把Man和Woman想成是不同密码加密方式,而run方法则是他们都需要实现的密码加密方法。
那我们试着让这几个类型实例化。
/** * @Author: Alickx * @Date: 2022/06/12/9:13 * @Description: main方法 */public class Demo8 { public static void main(String[] args) { // 使用man来实例化 IRun human1 = new Man(); human1.run(); // 使用woman来实例化 IRun human2 = new Woman(); human2.run(); }}
这里可以看出假如我们要将Man所实现的run要替换成Woman,我们并不需要修改很多代码,只需要将IRun human1 = new Man(); 替换成IRun human1 = new Woman(); 即可
实际项目改造
那使用多态这种特性,我们就可以创建一个统一的接口,业务代码都使用这个接口的方法,而通过实现该接口的方法,从而可以选择多种不同的实现方式。
那先创建一个AuthService接口,接口里面包含着我们业务代码所需要的api方法。
然后创建AuthSatokenServiceImpl 实现类,该实现类是使用Satoken来实现接口里面的方法。
简单调用一下Satoken的Api方法。
那么接口有了,实现类有了,但是在Springboot项目中,我们将实例化交给了Spring来管理,所以还需要创建一个配置类,来让Spring选择需要实例化的类。
Ok,那我们直接修改项目中的代码,这里举例一处。
原先的业务代码。
想以上红圈内的代码,我们需要获取当前请求的用户是否登录了,假如我们直接使用Satoken的API方法,那么后面需要更换SpringSecurity或者其他一些组件的时候,就需要大面积的修改这些代码。
改造后:
先注入实现类
@AutowiredAuthService authService;
这样子就完成了解耦,假如需要更换其他的授权认证组件,只需要创建一个实现AuthService接口的实现类,然后修改一下配置类的实例即可。
更改该处即可,即可更换。