更新時間:2018年12月07日13時58分 來源:傳智播客 瀏覽次數:
SpringSecurity方法級別的權限控制
引言
Spring Security是一個能夠為基于Spring的企業(yè)應用系統(tǒng)提供安全訪問控制解決方案的安全框架,它利用Spring IOC、DI和AOP功能,為企業(yè)應用系統(tǒng)提供聲明式的安全訪問控制功能,簡化企業(yè)系統(tǒng)為了安全控制而編寫大量重復代碼的工作,Spring Security支持Url級別的權限控制,同樣也支持方法級別的權限控制,今天主要介紹Spring Security方法級別的權限控制。
Spring Security方法級別權限控制方式
Spring Security方法級別權限控制主要有以下幾種方式:
• intercept-methods定義方法權限控制。
• 使用pointcut定義方法權限控制。
• 使用JSR-250注解定義方法權限控制。
• 使用@Secured注解定義方法權限控制。
• 注解使用表達式定義方法權限控制。
項目搭建
要想實現Spring Security方法級別的權限控制,必須先將項目搭建起來。
創(chuàng)建名稱為Spring-Security的web項目
在pom.xml文件中引入相關的依賴包。
/** * 單例設計模式之 懶漢式 * @author nianqiang */ public class SingletonClass { // 私有化及volatile修飾成員類 private static volatile SingletonClass instance = null; // 向外提供靜態(tài)創(chuàng)建對象實例 public static SingletonClass getInstance() { // 只有調用當前靜態(tài)方法,才返回當前類的實例 if (instance == null) { instance = new SingletonClass(); } return instance; } // 私有化構造 private SingletonClass() { } } |
public static void main(String[] args) { for (int i = 0; i < 10; i++) { SingletonClass singletonClass = SingletonClass.getInstance(); System.out.println(singletonClass); } } |
/** * java 設計模式之 餓漢式實現 * @author nianqiang */ public class Singleton { // 私有化構造 private Singleton() {} // 設置成員屬性時就創(chuàng)建當前的實例 private static final Singleton instance = new Singleton(); // 向外提供靜態(tài)方法訪問返回該類的實例 public static Singleton getInstance() { return instance; } } |
public static void main(String[] args) { for (int i = 0; i < 10; i++) { Singleton singleton = Singleton.getInstance(); System.out.println(singleton); } } |
/** * Java設計模式之雙重檢查鎖單例 * @author nianqiang */ public class Singleton { private static volatile Singleton instance = null; private Singleton() {} public static Singleton getInstance() { if (instance == null) { synchronized (Singleton1.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } } |
public static void main(String[] args) { for (int i = 0; i < 10; i++) { Singleton singleton = Singleton.getInstance(); System.out.println(singleton); } } |
上述的設計是當前用的比較多的一種,也是設計的比較巧妙的方式。我們接下來就仔細的分析一下上面的單例模式。
• 懶漢式的加強版:保證第一次使用的時候創(chuàng)建該類的實體對象。
• 線程安全:在多線程環(huán)境中如何高效的使用線程鎖機制來解決線程安全的問題,這里的設計是使用同步代碼塊最大限度的提高效率。
• 提高性能:在多線程環(huán)境下,如果只有一次檢查if (instance == null) 的話,相當于為了解決 1% 幾率的同步問題,而使用了一個 100% 出現的防護盾。雙重檢查就是把 100% 出現的防護盾,也改為 1% 的幾率出現。只有 instance 為 null 的時候,才進入 synchronized 的代碼段——大大減少了幾率。
• private static volatile Singleton instance = null;
關鍵詞 volatile 的作用:
– 內存可見性:可見性的意思是當一個線程修改一個共享變量時,另外一個線程能讀到這個修改的值。就是相當于共享同一塊內存區(qū)域。
– 禁止指令重排:雙重檢查鎖單例中利用的就是這一點。 那什么是指令重排呢?指令重排是指計算機為了提高執(zhí)行效率,會做一些優(yōu)化,在不影響最終結果的情況下,可能會對一些語句的執(zhí)行順序進行調整。
3.4. 靜態(tài)內部類單例
/** * 單例設計模式之靜態(tài)內部類實現 * * @author nianqiang */ public class Singleton { // 提供私有構造,目的防止外部new對象 private Singleton() { } // 私有靜態(tài)內部類提供當前對象的的實例 private static class InnerClass { private static final Singleton INSTANCE = new Singleton(); } // 外部提供當前類的對象的實例 public static Singleton getInstance() { return InnerClass.INSTANCE; } } |
public static void main(String[] args) { for (int i = 0; i < 10; i++) { Singleton singleton = Singleton.getInstance(); System.out.println(singleton); } } |
上述內部類實現的單例中,由于 InnerClass 是一個內部類,只在外部類的 Singleton 的 getInstance() 中被使用,所以它被加載的時機只會在 getInstance() 方法第一次被調用的時候。并且 InnerClass 初始化的時候會由 ClassLoader 來保證同步。 這種設計單例是一個巧妙的利用的內部類的加載機制來實現的,但是為什么只能是靜態(tài)的內部類呢?如果內部類不是靜態(tài)的結果如何呢? 答案是必須要把內部類設置成靜態(tài)的,如果內部類設置的不是靜態(tài)的,那么編譯器會報一個異常信息如下:
那么我們來解釋一下出現上述問題的原因,如果使用一個類的靜態(tài)成員,需要先把這個類加載到虛擬機中,而成員內部類是需要由外部類對象 new 一個實例才可以使用,這就無法做到靜態(tài)成員的要求。所以 Java 不允許非靜態(tài)內部類持有靜態(tài)的聲明。此時必須將當前的內部類加上static修飾。
4. 總結
以上我們就學習了關于設計模式中的單例模式在實際開發(fā)中常用的實現方式,以及各個實現方式的優(yōu)缺點,那么在開發(fā)中根據實際的業(yè)務需求選擇不同的單例模式即可。一般情況下單例模式在多線程環(huán)境下使用的時候需要特別注意的是線程安全相關的問題。