最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

在Java Spring框架中使用的設(shè)計(jì)模式有哪些

 更新時(shí)間:2021年09月15日 15:28:14   作者:JavaEdge.  
面試中常會(huì)被問道Spring框架使用了哪些設(shè)計(jì)模式?關(guān)于這個(gè)問題本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

1 簡單工廠模式

當(dāng)A對(duì)象需要調(diào)用B對(duì)象的方法時(shí),我們需要在A中new一個(gè)B的實(shí)例,我們把這種方式叫作硬編碼耦合,缺點(diǎn)是一旦需求發(fā)生變化,比如需要使用C類來代替B時(shí),就要改寫A類的方法。

假如應(yīng)用中有上千個(gè)類以硬編碼的方式耦合了B,改就很頭疼。
于是有了簡單工廠模式,又叫靜態(tài)工廠方法,就是由一個(gè)工廠類根據(jù)傳入?yún)?shù),動(dòng)態(tài)決定應(yīng)該創(chuàng)建哪個(gè)產(chǎn)品類。

Spring中的BeanFactory就是簡單工廠模式的體現(xiàn),BeanFactory是Spring IOC容器中的一個(gè)核心接口,它的定義如下:

可以通過它的具體實(shí)現(xiàn)類(如ClassPathXmlApplicationContext)獲取Bean:

BeanFactory bf = new ClassPathXmlApplicationContext("spring.xml");
User userBean = (User) bf.getBean("userBean");

使用者無需自己new,而是通過工廠類的方法getBean獲取對(duì)象實(shí)例,這就是簡單工廠模式,只不過Spring是用反射創(chuàng)建Bean。

2 工廠方法模式

簡單工廠中,由工廠類進(jìn)行所有的邏輯判斷、實(shí)例創(chuàng)建。
如果不想在工廠類中進(jìn)行判斷,可為不同產(chǎn)品提供不同工廠,不同工廠生產(chǎn)不同產(chǎn)品,每個(gè)工廠都只對(duì)應(yīng)一個(gè)相應(yīng)對(duì)象,這就是工廠方法模式。

Spring FactoryBean,工廠Bean

定義一個(gè)類UserFactoryBean實(shí)現(xiàn)FactoryBean接口,主要是在getObject方法里new一個(gè)User對(duì)象。
這樣通過getBean(id) 獲得的是該工廠所產(chǎn)生的User實(shí)例,而非UserFactoryBean本身實(shí)例:

BeanFactory bf = new ClassPathXmlApplicationContext("user.xml");
User userBean = (User) bf.getBean("userFactoryBean");

3 單例模式

一個(gè)類在整個(gè)系統(tǒng)運(yùn)行過程中,只允許產(chǎn)生一個(gè)實(shí)例。

Spring Bean默認(rèn)是單例模式。Spring 通過單例注冊(cè)表(HashMap)方式:

public class DefaultSingletonBeanRegistry {
    
    // 使用 ConcurrentHashMap 保存各種單實(shí)例對(duì)象
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>;

    protected Object getSingleton(String beanName) {
    // 先到 Map 中拿Object
    Object singletonObject = singletonObjects.get(beanName);
    
    // 若沒拿到通過反射創(chuàng)建一個(gè)對(duì)象實(shí)例,并添加到HashMap中
    if (singletonObject == null) {
      singletonObjects.put(beanName,
                           Class.forName(beanName).newInstance());
   }
   
   // 返回對(duì)象實(shí)例
   return singletonObjects.get(beanName);
  }
}

4 代理模式

它與被代理對(duì)象實(shí)現(xiàn)相同接口,客戶端必須通過代理才能與被代理的目標(biāo)類進(jìn)行交互,而代理一般在交互的過程中(交互前后),進(jìn)行某些特定處理,比如在調(diào)用這個(gè)方法前做前置處理,調(diào)用這個(gè)方法后做后置處理。

好處

可以在目標(biāo)對(duì)象業(yè)務(wù)功能的基礎(chǔ)上添加一些公共的邏輯,比如我們想給目標(biāo)對(duì)象加入日志、權(quán)限管理和事務(wù)控制等功能,我們就可以使用代理類來完成,而沒必要修改目標(biāo)類,從而使得目標(biāo)類保持穩(wěn)定。

符合開閉原則,不要隨意修改別人寫好的代碼或方法。

代理又分為

靜態(tài)代理

需要定義接口,被代理對(duì)象(目標(biāo)對(duì)象)與代理對(duì)象(Proxy)一起實(shí)現(xiàn)相同接口:

// 抽象接口
public interface IStudentDao {
    void save();
}

// 目標(biāo)對(duì)象
public class StudentDao implements IStudentDao {
    public void save() {
        System.out.println("保存成功");
    }
}

// 代理對(duì)象
public class StudentDaoProxy implements IStudentDao{
    //持有目標(biāo)對(duì)象的引用
    private IStudentDao target;
    public StudentDaoProxy(IStudentDao target){
        this.target = target;
    }

    //在目標(biāo)功能對(duì)象方法的前后加入事務(wù)控制
    public void save() {
        System.out.println("開始事務(wù)");
        target.save();//執(zhí)行目標(biāo)對(duì)象的方法
        System.out.println("提交事務(wù)");
    }
}

public static void main(String[] args) {
    //創(chuàng)建目標(biāo)對(duì)象
    StudentDao target = new StudentDao();

    //創(chuàng)建代理對(duì)象,把目標(biāo)對(duì)象傳給代理對(duì)象,建立代理關(guān)系
    StudentDaoProxy proxy = new StudentDaoProxy(target);
   
    //執(zhí)行的是代理的方法
    proxy.save();
}

動(dòng)態(tài)代理

Spring AOP采用動(dòng)態(tài)代理,即代理類在程序運(yùn)行時(shí)由JVM動(dòng)態(tài)創(chuàng)建。
靜態(tài)代理的例子中,代理類(StudentDaoProxy)是自定義的,在程序運(yùn)行之前就已經(jīng)編譯完成。
而動(dòng)態(tài)代理,代理類并不是在Java代碼中定義,而是在運(yùn)行時(shí)根據(jù)我們?cè)贘ava代碼中的“指示”動(dòng)態(tài)生成的。

怎么“指示”JDK去動(dòng)態(tài)地生成代理類呢?

在Java的java.lang.reflect包里提供了一個(gè)Proxy類和一個(gè)InvocationHandler接口,通過這個(gè)類和這個(gè)接口可以生成動(dòng)態(tài)代理對(duì)象:
1.定義一個(gè)InvocationHandler類,將需要擴(kuò)展的邏輯集中放到這個(gè)類中。
比如下面的例子模擬了添加事務(wù)控制:

public class MyInvocationHandler implements InvocationHandler {

    private Object obj;

    public MyInvocationHandler(Object obj){
        this.obj=obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {

        System.out.println("開始事務(wù)");
        Object result = method.invoke(obj, args);
        System.out.println("開始事務(wù)");
        
        return result;
    }
}

2.使用 Proxy#newProxyInstance 動(dòng)態(tài)創(chuàng)建代理對(duì)象

public static void main(String[] args) {
  //創(chuàng)建目標(biāo)對(duì)象StudentDao
  IStudentDao stuDAO = new StudentDao();
  
  //創(chuàng)建MyInvocationHandler對(duì)象
  InvocationHandler handler = new MyInvocationHandler(stuDAO);
  
  //使用Proxy.newProxyInstance動(dòng)態(tài)的創(chuàng)建代理對(duì)象stuProxy
  IStudentDao stuProxy = (IStudentDao) 
 Proxy.newProxyInstance(stuDAO.getClass().getClassLoader(), stuDAO.getClass().getInterfaces(), handler);
  
  //動(dòng)用代理對(duì)象的方法
  stuProxy.save();
}

動(dòng)態(tài)代理的優(yōu)勢(shì)在于可以很方便地對(duì)代理類的函數(shù)進(jìn)行統(tǒng)一的處理,而不用修改每個(gè)代理類中的方法。

Spring實(shí)現(xiàn)了通過動(dòng)態(tài)代理對(duì)類進(jìn)行方法級(jí)別的切面增強(qiáng),即動(dòng)態(tài)生成目標(biāo)對(duì)象的代理類,并在代理類的方法中設(shè)置攔截器,通過執(zhí)行攔截器中的邏輯增強(qiáng)了代理方法的功能,從而實(shí)現(xiàn)AOP。

到此這篇關(guān)于在Java Spring框架中使用的設(shè)計(jì)模式有哪些的文章就介紹到這了,更多相關(guān)Java Spring 設(shè)計(jì)模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java實(shí)現(xiàn)的數(shù)字簽名算法RSA完整示例

    Java實(shí)現(xiàn)的數(shù)字簽名算法RSA完整示例

    這篇文章主要介紹了Java實(shí)現(xiàn)的數(shù)字簽名算法RSA,結(jié)合完整實(shí)例形式詳細(xì)分析了RSA算法的相關(guān)概念、原理、實(shí)現(xiàn)方法及操作技巧,需要的朋友可以參考下
    2019-09-09
  • java實(shí)現(xiàn)獲取安卓設(shè)備里已安裝的軟件包

    java實(shí)現(xiàn)獲取安卓設(shè)備里已安裝的軟件包

    本文給大家介紹的是如何獲取設(shè)備中已經(jīng)安裝的應(yīng)用軟件包的代碼,其核心方法原理很簡單,我們通過Android中提供的PackageManager類,來獲取手機(jī)中安裝的應(yīng)用程序信息
    2015-10-10
  • java使用反射給對(duì)象屬性賦值的兩種方法

    java使用反射給對(duì)象屬性賦值的兩種方法

    JAVA反射機(jī)制是在運(yùn)行狀態(tài)中,對(duì)于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法,下面這篇文章主要給大家介紹了關(guān)于java使用反射給對(duì)象屬性賦值的兩種方法,需要的朋友可以參考下
    2023-04-04
  • java如何接收和發(fā)送ASCII數(shù)據(jù)

    java如何接收和發(fā)送ASCII數(shù)據(jù)

    這篇文章主要介紹了java如何接收和發(fā)送ASCII數(shù)據(jù)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • mybatis配置mapper-locations的坑及解決

    mybatis配置mapper-locations的坑及解決

    這篇文章主要介紹了mybatis配置mapper-locations的坑及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • 深入解析Java中ThreadLocal線程類的作用和用法

    深入解析Java中ThreadLocal線程類的作用和用法

    ThreadLocal為解決多線程程序的并發(fā)問題提供了一種新的思路,ThreadLocal并不是一個(gè)Thread,而是Thread的局部變量,本文就來深入解析Java中ThreadLocal線程類的作用和用法.
    2016-05-05
  • java修改JFrame默認(rèn)字體方式

    java修改JFrame默認(rèn)字體方式

    這篇文章主要介紹了java修改JFrame默認(rèn)字體方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • javaDSL簡單實(shí)現(xiàn)示例分享

    javaDSL簡單實(shí)現(xiàn)示例分享

    DSL領(lǐng)域定義語言,用來描述特定領(lǐng)域的特定表達(dá)。比如畫圖從起點(diǎn)到終點(diǎn);路由中的從A到B。這是關(guān)于畫圖的一個(gè)簡單實(shí)現(xiàn)
    2014-03-03
  • 如何設(shè)置Spring Boot測(cè)試時(shí)的日志級(jí)別

    如何設(shè)置Spring Boot測(cè)試時(shí)的日志級(jí)別

    Spring Boot是由Pivotal團(tuán)隊(duì)提供的全新框架,其設(shè)計(jì)目的是用來簡化新Spring應(yīng)用的初始搭建以及開發(fā)過程。該框架使用了特定的方式來進(jìn)行配置,從而使開發(fā)人員不再需要定義樣板化的配置。下面我們來一起學(xué)習(xí)一下吧
    2019-06-06
  • javascript最新2020經(jīng)典面試題

    javascript最新2020經(jīng)典面試題

    這篇文章主要介紹了javascript最新2020經(jīng)典面試題的相關(guān)內(nèi)容,有需要的朋友們可以學(xué)習(xí)下。
    2020-02-02

最新評(píng)論

四子王旗| 通江县| 黄龙县| 资溪县| 安国市| 崇信县| 青神县| 乌海市| 涟源市| 乐亭县| 上蔡县| 新巴尔虎右旗| 博湖县| 上犹县| 祁连县| 高密市| 且末县| 永定县| 比如县| 石狮市| 潜江市| 施秉县| 丰镇市| 翁源县| 绵阳市| 洛南县| 乌拉特前旗| 广汉市| 榕江县| 个旧市| 晋城| 巴林左旗| 井研县| 九龙坡区| 叙永县| 邵阳县| 安阳县| 石台县| 西乌珠穆沁旗| 云和县| 和林格尔县|