springboot~通過面向(xiang)接口編程對(dui)控制反轉IOC的理解
IOC,把(ba)控制反轉到業務端,這(zhe)句話沒(mei)什(shen)么問(wen)題,在(zai)springboot框架里(li),對象的(de)(de)管理是通(tong)過spring ioc來實現的(de)(de),而(er)開發人(ren)員的(de)(de)開發原則里(li)總(zong)是說(shuo)“面向(xiang)接口(kou)編程”,而(er)為(wei)什(shen)么要面向(xiang)接口(kou)卻沒(mei)幾(ji)個人(ren)能說(shuo)出來,今天在(zai)寫(xie)一(yi)個基于redis的(de)(de)手動分布鎖時,對這(zhe)個面向(xiang)接口(kou)和控制反轉又有了一(yi)個體會。
底層代碼更需要面向接口
當你為開發人員提供一個封閉的包時,他們是直接用的,他們不會修改你的代碼,當然他們可以去繼承并擴展;當然如果你不希望被繼承可以聲明為final,這都是面向對象編程里提供好的功能,我們主要看控制反轉這句話,它把控制權交給了上層去實現,底層通過 面向接口 的(de)原則只設計一(yi)個規范,而又(you)使用(yong)者去實(shi)現(xian);但框架功能(neng)里的(de)細節(jie)是要有的(de),這類似于“模(mo)版方法(fa)”模(mo)式,底(di)層框架實(shi)現(xian)了(le)流(liu)程,而個性化的(de)部分(fen)由上(shang)層去實(shi)現(xian)。
看jpa里的審計接口
public interface AuditorAware<T> {
/**
* Returns the current auditor of the application.
*
* @return the current auditor
*/
Optional<T> getCurrentAuditor();
}
上(shang)(shang)面這個(ge)(ge)泛型接(jie)(jie)(jie)口只有一個(ge)(ge)方法,需要讓上(shang)(shang)層開發(fa)人(ren)員根(gen)據自己的(de)(de)業務去實(shi)(shi)現它,比較返(fan)(fan)回(hui)一個(ge)(ge)當(dang)前登(deng)陸的(de)(de)用戶實(shi)(shi)體,或(huo)者返(fan)(fan)回(hui)用戶名稱(cheng),然后底(di)層框(kuang)架里直接(jie)(jie)(jie)使用這個(ge)(ge)AuditorAware接(jie)(jie)(jie)口的(de)(de)對象;當(dang)然如果你的(de)(de)底(di)層只接(jie)(jie)(jie)收一個(ge)(ge)String類型的(de)(de)值,你也可以去派生一個(ge)(ge)個(ge)(ge)性化接(jie)(jie)(jie)口,讓上(shang)(shang)層開發(fa)人(ren)員去實(shi)(shi)現你的(de)(de)接(jie)(jie)(jie)口即可。
/**
* 返回用戶ID的標識接口,由程序使用者去實現.
*/
public interface UserIdAuditorAware extends AuditorAware<String> {
}
上(shang)面代碼更加準確的規定了AuditorAware是一個字符串的接(jie)口(kou),只(zhi)返回用戶ID即可(ke)。
@Component
public class CurrentUserAware implements UserIdAuditorAware {
@Autowired
ApplicationContext applicationContext;
@Override
public Optional<String> getCurrentAuditor() {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest();
return Optional.of(request.getSession().getAttribute("id").toString());
}
}
我們的底層代碼會使用它的getCurrentAuditor()返回值(zhi) ,它是一個字符串。
public Object execute(String sourceId, Integer timeout, TimeUnit unit) {
Assert.notNull(sourceId, "sourceId不能為空");
String key = getKey(sourceId);
String user = auditorAware.getCurrentAuditor().orElse(null);
Assert.notNull(user, "AuditorAware實例返回的值為空");
// 代碼略
}
對于一(yi)個(ge)小小的(de)功(gong)能,我(wo)們在經過(guo)思考之后(hou),對于之前學(xue)過(guo)的(de)東西進行總結,你可(ke)能會想法某(mou)種(zhong)設計模式、某(mou)個(ge)算(suan)法、某(mou)個(ge)原則(ze)、在使用(yong)它們之后(hou),讓你的(de)代碼擴展性更好(hao),這種(zhong)代碼也仿佛有了生命!