傳智播客旗下品牌:|||||

全國咨詢/投訴熱線:400-618-4000

Java設計模式之單例模式以及單例所引發的思考

更新時間:2018年12月07日13時58分 來源:傳智播客 瀏覽次數:

SpringSecurity方法級別的權限控制

引言

Spring Security是一個能夠為基于Spring的企業應用系統提供安全訪問控制解決方案的安全框架,它利用Spring IOC、DI和AOP功能,為企業應用系統提供聲明式的安全訪問控制功能,簡化企業系統為了安全控制而編寫大量重復代碼的工作,Spring Security支持Url級別的權限控制,同樣也支持方法級別的權限控制,今天主要介紹Spring Security方法級別的權限控制。

Spring Security方法級別權限控制方式

Spring Security方法級別權限控制主要有以下幾種方式:

• intercept-methods定義方法權限控制。

• 使用pointcut定義方法權限控制。

• 使用JSR-250注解定義方法權限控制。

• 使用@Secured注解定義方法權限控制。

• 注解使用表達式定義方法權限控制。

項目搭建

要想實現Spring Security方法級別的權限控制,必須先將項目搭建起來。

創建名稱為Spring-Security的web項目

在pom.xml文件中引入相關的依賴包。

/**
 * 單例設計模式之 懶漢式
 * @author nianqiang
 */
public class SingletonClass {
   
    // 私有化及volatile修飾成員類
    private static volatile SingletonClass instance = null;

    // 向外提供靜態創建對象實例
    public static SingletonClass getInstance() {
           // 只有調用當前靜態方法,才返回當前類的實例
           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

3.2. 餓漢式單例

 
/**
 * java 設計模式之 餓漢式實現
 * @author nianqiang
 */
public class Singleton {

    // 私有化構造
    private Singleton() {}

    // 設置成員屬性時就創建當前的實例
    private static final Singleton instance = new Singleton();

    // 向外提供靜態方法訪問返回該類的實例
    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
由上述實現方式,我們可以得到結論:餓漢式單例中 instance 的初始化是在類加載時進行的,而類的加載是由 ClassLoader 來完成,這個過程由 JVM 來保證同步,所以這種方式天生是線程安全的。它的缺點也顯而易見:容易造成資源的浪費,并且如果構造方法中處理過多,還有可能引發性能問題。

3.3. 雙重檢查鎖單例

 
/**
 * 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);
    }
}
 
結果:
java

上述的設計是當前用的比較多的一種,也是設計的比較巧妙的方式。我們接下來就仔細的分析一下上面的單例模式。

• 懶漢式的加強版:保證第一次使用的時候創建該類的實體對象。

• 線程安全:在多線程環境中如何高效的使用線程鎖機制來解決線程安全的問題,這里的設計是使用同步代碼塊最大限度的提高效率。

• 提高性能:在多線程環境下,如果只有一次檢查if (instance == null) 的話,相當于為了解決 1% 幾率的同步問題,而使用了一個 100% 出現的防護盾。雙重檢查就是把 100% 出現的防護盾,也改為 1% 的幾率出現。只有 instance 為 null 的時候,才進入 synchronized 的代碼段——大大減少了幾率。

• private static volatile Singleton instance = null;

關鍵詞 volatile 的作用:

– 內存可見性:可見性的意思是當一個線程修改一個共享變量時,另外一個線程能讀到這個修改的值。就是相當于共享同一塊內存區域。

– 禁止指令重排:雙重檢查鎖單例中利用的就是這一點。 那什么是指令重排呢?指令重排是指計算機為了提高執行效率,會做一些優化,在不影響最終結果的情況下,可能會對一些語句的執行順序進行調整。

3.4. 靜態內部類單例

/**
 * 單例設計模式之靜態內部類實現
 *
 * @author nianqiang
 */
public class Singleton {

    // 提供私有構造,目的防止外部new對象
    private Singleton() { }

    // 私有靜態內部類提供當前對象的的實例
    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);
    }
}
 
結果:
java

上述內部類實現的單例中,由于 InnerClass 是一個內部類,只在外部類的 Singleton 的 getInstance() 中被使用,所以它被加載的時機只會在 getInstance() 方法第一次被調用的時候。并且 InnerClass 初始化的時候會由 ClassLoader 來保證同步。 這種設計單例是一個巧妙的利用的內部類的加載機制來實現的,但是為什么只能是靜態的內部類呢?如果內部類不是靜態的結果如何呢? 答案是必須要把內部類設置成靜態的,如果內部類設置的不是靜態的,那么編譯器會報一個異常信息如下:

java

那么我們來解釋一下出現上述問題的原因,如果使用一個類的靜態成員,需要先把這個類加載到虛擬機中,而成員內部類是需要由外部類對象 new 一個實例才可以使用,這就無法做到靜態成員的要求。所以 Java 不允許非靜態內部類持有靜態的聲明。此時必須將當前的內部類加上static修飾。

4. 總結

以上我們就學習了關于設計模式中的單例模式在實際開發中常用的實現方式,以及各個實現方式的優缺點,那么在開發中根據實際的業務需求選擇不同的單例模式即可。一般情況下單例模式在多線程環境下使用的時候需要特別注意的是線程安全相關的問題。

javaee

python

web

ui

cloud

test

c

netmarket

pm

Linux

movies

robot

uids

北京校區

    14天免費試學

    基礎班入門課程限時免費

    申請試學名額

    15天免費試學

    基礎班入門課程限時免費

    申請試學名額

    15天免費試學

    基礎班入門課程限時免費

    申請試學名額

    15天免費試學

    基礎班入門課程限時免費

    申請試學名額

    20天免費試學

    基礎班入門課程限時免費

    申請試學名額

    8天免費試學

    基礎班入門課程限時免費

    申請試學名額

    20天免費試學

    基礎班入門課程限時免費

    申請試學名額

    5天免費試學

    基礎班入門課程限時免費

    申請試學名額

    0天免費試學

    基礎班入門課程限時免費

    申請試學名額

    12天免費試學

    基礎班入門課程限時免費

    申請試學名額

    5天免費試學

    基礎班入門課程限時免費

    申請試學名額

    5天免費試學

    基礎班入門課程限時免費

    申請試學名額

    10天免費試學

    基礎班入門課程限時免費

    申請試學名額
    网赚联盟是真的吗 疯狂斗牛 投票网赚 网赚联盟是真的吗 做网赚什么软件好 广发彩票 在家上网赚点小钱 幸运飞艇直播链接 北京赛车 金旋风网赚