久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Spring框架基礎(chǔ)知識(shí)(01)

 海擁 2021-11-30

1. 什么是框架

框架在項(xiàng)目中的表現(xiàn)就是一系列的jar包,例如Thymeleaf就是一個(gè)框架。

每種框架都會(huì)解決某種特定的問題,可能是開發(fā)效率的問題,或運(yùn)行效率的問題,或代碼管理維護(hù)的問題等等。

項(xiàng)目中使用框架就相當(dāng)于得到了一個(gè)“毛坯房”,使用了框架之后,開發(fā)人員只需要關(guān)心后續(xù)的“裝修”即可,。

絕大部分的框架都有特定的使用方式,在使用時(shí),必須遵循框架的使用規(guī)則!

每個(gè)框架都可能是若干個(gè)開發(fā)人員甚至開發(fā)團(tuán)隊(duì)多年的工作積累的作品,對于初學(xué)者來說,不要過于鉆牛角尖,嘗試?yán)斫饪蚣艿牡讓訉?shí)現(xiàn)原理!

簡單的說:使用框架,可以讓編程變得更加簡單!在學(xué)習(xí)框架時(shí),主要學(xué)習(xí)框架的正確使用方式!

2. 依賴關(guān)系

假設(shè)在項(xiàng)目中需要開發(fā)一個(gè)用戶注冊的功能!在項(xiàng)目中可能存在:

public class UserRegServlet {
    private UserDao userDao = new UserDao();
    
    public void doPost() {
        userDao.reg(); // 調(diào)用userDao對象實(shí)現(xiàn)存儲(chǔ)用戶數(shù)據(jù)
    }
}
public class UserDao {
    public void reg() {
        // 通過JDBC技術(shù)將用戶數(shù)據(jù)存儲(chǔ)到數(shù)據(jù)庫中
    }
}

在以上代碼中,UserRegServlet就是依賴UserDao的!

3. 耦合度

如果某個(gè)類過于依賴于另外一個(gè)類,通常稱之為了“耦合度較高”,是不利于代碼的管理和維護(hù)的,簡單的說,如果UserRegServlet依賴于UserDao,在未來的某一天,UserDao已經(jīng)不能滿足項(xiàng)目的需求了(可能是因?yàn)榇a有Bug,或者使用的技術(shù)比較落后等),如果需要把UserDao替換掉,替換難度大就會(huì)影響項(xiàng)目的管理和維護(hù),為了解決這樣的問題采取的解決方案就稱之為“解耦”,使得依賴關(guān)系不那么明確,甚至就是不明確!

就以上UserRegServlet依賴UserDao的問題,如果要解耦,可以先創(chuàng)建一個(gè)接口:

public interface IUserDao {
    void reg();
}

然后,使得UserDao是實(shí)現(xiàn)了以上接口的:

public class UserDao implements IUserDao {
    public void reg() {
        // 具體的實(shí)現(xiàn)了reg()方法應(yīng)該實(shí)現(xiàn)的功能
    }
}

經(jīng)過以上調(diào)整以后,如果在UserRegServlet中需要使用到UserDao,以前的代碼是這樣的:

private UserDao userDao = new UserDao();

現(xiàn)在就可以改為:

private IUserDao userDao = new UserDao();

以上代碼就相當(dāng)于:

private List<String> strings = new ArrayList<>();

改成這樣以后,在同一個(gè)項(xiàng)目中,無論多少個(gè)Servlet組件需要使用到UserDao,都可以使用以上“聲明為接口,創(chuàng)建實(shí)現(xiàn)類的對象”的語法風(fēng)格,如果以后UserDao需要被替換掉,也只需要替換“賦值”的代碼,聲明部分是不需要替換的!例如需要把UserDao替換為UserMybatisDao時(shí),原來的代碼是:

private IUserDao userDao = new UserDao();

新的代碼就可以是:

public class UserMybatisDao implements IUserDao {
    public void reg() {
        // 使用更好的方式實(shí)現(xiàn)reg()應(yīng)該實(shí)現(xiàn)的功能
    }
}

在后續(xù)的使用中,就可以是:

private IUserDao userDao = new UserMybatisDao();

也就是說,在UserDao換成了UserMybatisDao時(shí),在各個(gè)Servlet中,都只需要調(diào)整等于號(hào)右側(cè)的內(nèi)容,而不再需要修改等于號(hào)左側(cè)的部分!

當(dāng)然,關(guān)于以上代碼的右側(cè)部分,還可以使用“工廠設(shè)計(jì)模式”作進(jìn)一步的處理:

public class UserDaoFactory {
    // 返回接口類型的對象
    public static IUserDao newInstance() {
        return new UserDao(); // 也可以返回UserMybatisDao的對象
    }
}

當(dāng)有了工廠后,此前的代碼就可以進(jìn)一步調(diào)整為:

private IUserDao userDao = UserDaoFactory.newInstance();

可以發(fā)現(xiàn),以上代碼中不再出現(xiàn)任何一個(gè)實(shí)現(xiàn)類的名字了,無論是哪個(gè)Servlet組件需要訪問數(shù)據(jù)庫,都聲明為以上代碼即可,以后,如果實(shí)現(xiàn)類需要被替換,也只需要替換工廠方法的返回值即可!

在實(shí)際項(xiàng)目開發(fā)時(shí),項(xiàng)目中的組件的依賴更加復(fù)雜,為每個(gè)組件都創(chuàng)建對應(yīng)的接口及工廠是非常麻煩的,而Spring框架就很好的解決了這個(gè)問題,可以簡單的將Spring理解為一個(gè)“萬能工廠”,當(dāng)使用了Spring框架后,就不必自行開發(fā)工廠了!

4. Spring框架簡介

Spring框架的主要作用:解決了創(chuàng)建對象和管理對象的問題,。

5. 通過Spring創(chuàng)建對象

創(chuàng)建Maven Project,在創(chuàng)建過程中,勾選Create a simple projectGroup Id填為cn.teduArtifact Id填為spring01,其它項(xiàng)保持默認(rèn)即可,。

使用Spring框架時(shí),必須在項(xiàng)目的pom.xml中添加spring-context的依賴:

<!-- https:///artifact/org.springframework/spring-context -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.5.RELEASE</version>
</dependency>

首先,在項(xiàng)目中,創(chuàng)建cn.tedu.spring包,并在這個(gè)包下創(chuàng)建BeanFactory類:

package cn.tedu.spring;

public class BeanFactory {

}

當(dāng)前,代碼放在哪個(gè)包中并不重要,應(yīng)該養(yǎng)成習(xí)慣,每個(gè)類都應(yīng)該放在某個(gè)包中,不要讓任何類不放在任何包中!

以上類的名稱也不重要,是自定義的!

如果希望由Spring來創(chuàng)建并管理某個(gè)類的對象,必須在以上類中添加方法,關(guān)于這個(gè)方法:

  • 應(yīng)該使用public權(quán)限;
  • 返回值類型就是需要Spring創(chuàng)建并管理的類的對象的類型;
  • 方法名稱可以自定義;
  • 參數(shù)列表暫時(shí)為空;
  • 在方法體中,自行編寫創(chuàng)建返回值對象的代碼,。

假設(shè)需要Spring來創(chuàng)建Date類型的對象,則在類中添加方法:

public Date aaa() {
    // 規(guī)范,規(guī)則
}

Spring框架要求:創(chuàng)建對象的方法必須添加@Bean注解,并且,這樣的方法必須在配置類中!任何一個(gè)類添加了@Configuration注解都可以作為配置類!

package cn.tedu.spring;

@Configuration
public class BeanFactory {

@Bean
public Date aaa() {
return new Date();
}

}

完成后,應(yīng)該使用一個(gè)可以運(yùn)行的類,或通過單元測試來檢驗(yàn)“是否可以通過Spring容器獲取對象”,。本次先創(chuàng)建一個(gè)可以運(yùn)行的類:

package cn.tedu.spring;

public class SpringTests {

public static void main(String[] args) {
// 1. 加載配置類,得到Spring容器
AnnotationConfigApplicationContext ac
= new AnnotationConfigApplicationContext(BeanFactory.class);

// 2. 從Spring容器中獲取所需要的對象
Date date = (Date) ac.getBean("aaa"); // getBean()方法的參數(shù)就是創(chuàng)建對象的方法的名稱

// 3. 測試獲取到的對象
System.out.println(date);

// 4. 關(guān)閉
ac.close();
}

}

6. 關(guān)于@Bean注解

當(dāng)方法的聲明之前添加了@Bean注解,就表示這個(gè)方法是需要由Spring框架所調(diào)用,并且,由Spring框架管理該方法返回的對象的!默認(rèn)情況下,該方法的名稱就是后續(xù)獲取對象時(shí),調(diào)用getBean()方法的參數(shù)!

由于添加了@Bean注解的方法是被Spring框架調(diào)用的,不需要自行編寫代碼來調(diào)用這個(gè)方法,所以,Spring的建議是“使用合理的屬性名稱作為方法名,并不需要使用動(dòng)詞或動(dòng)詞為前綴的方法名”,簡單的說,如果方法是為了獲取Date類型的對象的,該方法的名稱應(yīng)該是date,而不是getDate(),則后續(xù)調(diào)用getBean()時(shí),參數(shù)就是date這個(gè)名稱!

當(dāng)然,如果不遵循Spring的建議,還可以在@Bean注解中配置注解參數(shù)來指定Bean的名稱,例如:

@Bean("date")
public Date getDate() {
    return new Date();
}

則后續(xù)就根據(jù)注解參數(shù)來獲取對象:

Date date = (Date) ac.getBean("date");

其關(guān)系如下圖:

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-vQ4XyehG-1589893419503)(01.png)]

其實(shí),在開發(fā)項(xiàng)目時(shí),真的不必關(guān)心這些問題,也就是說,例如是一個(gè)獲取Date對象的方法,其名稱到底是date還是getDate都是正確的!畢竟這個(gè)方法最終就是由Spring框架來調(diào)用,開發(fā)人員不會(huì)自行調(diào)用該方法!

7. Spring管理對象的作用域

由Spring管理的對象,默認(rèn)情況下,是單例的!所以,其作用域就非常久!

在Spring管理對象的情況下,討論對象的作用域,其本質(zhì)就是討論其是否單例!

在創(chuàng)建對象的方法之前,添加@Scope注解,并配置注解參數(shù)為prototype,就可以使得該對象不是單例的:

@Scope("prototype")
@Bean
public User user() {
    return new User();
}

由Spring管理的對象,如果是單例模式的,默認(rèn)情況下,是餓漢式的!在創(chuàng)建對象的方法之前,添加@Lazy注解,就可以調(diào)整為懶漢式的:

@Bean
@Lazy
public User user() {
    return new User();
}

一般,在開發(fā)項(xiàng)目時(shí),極少調(diào)整對象的作用域!

8. 當(dāng)天小結(jié):

  • Spring的主要作用:創(chuàng)建對象,管理對象;
  • 如果某個(gè)方法是用于給Spring框架創(chuàng)建對象的,這個(gè)方法就必須添加@Bean注解;
  • 所有添加了@Bean注解的方法,其所在的類應(yīng)該添加@Configuration注解,凡添加了@Configuration注解的類稱之為配置類
  • 默認(rèn)情況下,由Spring管理的對象是單例的,使用@Scope注解可以將Spring管理的對象調(diào)整為“非單例”的;
  • 默認(rèn)情況下,由Spring管理的單例的對象是是“餓漢式”的,使用@Lazy可以將它們改為“懶漢式”的,。

附1:設(shè)計(jì)模式之單例模式

單例模式的特點(diǎn):在同一時(shí)期,某個(gè)類的對象一定最多只有1個(gè)!也許會(huì)嘗試多次的獲取對象,但是,獲取到的一定是同一個(gè)對象!

假設(shè)項(xiàng)目中有King類:

public class King {
}

很顯然,目前它并不是單例的,因?yàn)?#xff0c;可以:

King k1 = new King();
King k2 = new King();
King k3 = new King();

以上代碼就創(chuàng)建了3個(gè)King類型的對象!如果要實(shí)現(xiàn)單例,首先,就必須限制構(gòu)造方法的訪問,例如:

public class King {
    private King() {
    }
}

每個(gè)類中都可以有若干個(gè)構(gòu)造方法,如果某個(gè)類沒有顯式的聲明任何構(gòu)造方法,編譯器就會(huì)自動(dòng)添加1個(gè)公有的,、無參數(shù)的構(gòu)造方法!如果類中已經(jīng)聲明任何構(gòu)造方法,則編譯器不會(huì)自動(dòng)添加構(gòu)造方法!

由于將構(gòu)造方法聲明為私有的,則原有的King k1 = new King();這類代碼就不能用于創(chuàng)建對象了!

限制構(gòu)造方法的訪問,其目的是“不允許隨意創(chuàng)建對象”,并不是“不允許創(chuàng)建對象”,在King類的內(nèi)部,還是可以創(chuàng)建對象的,可以添加方法,返回內(nèi)部創(chuàng)建的對象:

public class King {
    private King king = new King();
    
    private King() {
    }
    
    public King getInstance() {
        return king;
    }
}

所以,當(dāng)需要King類型的對象時(shí),可以通過getInstance()方法來獲取!

但是,以上代碼是不可行的!因?yàn)?#xff0c;如果要調(diào)用getInstance()方法,必須先獲取King的對象,而獲取King對象的唯一方式就是調(diào)用getInstance()方法!為了解決這個(gè)問題,必須在getInstance()方法的聲明之前添加static修飾符,最終,就可以通過類名.方法名()的語法格式來調(diào)用方法了!同時(shí),由于“被static修飾的成員,不可以訪問其它未被static修飾的成員”,所以,全局屬性king也必須被static修飾:

public class King {
    private static King king = new King();
    
    private King() {
    }
    
    public static King getInstance() {
        return king;
    }
}

至此,基本的單例模式的代碼就設(shè)計(jì)完成了!

以上代碼是“餓漢式”的單例模式,另外,還有“懶漢式”的單例模式!

基本的懶漢式單例模式的代碼是:

public class King {
    private static King king = null;
    
    private King() {
    }
    
    public static King getInstance() {
        if (king == null) {
            king = new King();
        }
        return king;
    }
}

注意:以上代碼是多線程不安全的!

在開發(fā)領(lǐng)域中,只要數(shù)據(jù)的產(chǎn)生、變化不是開發(fā)人員預(yù)期的,就稱之為“不安全”,也就是“數(shù)據(jù)安全問題”,。

為了保障線程安全,應(yīng)該為以上創(chuàng)建對象的代碼片斷“加鎖”,例如:

public class King {
    private static King king = null;
    
    private King() {
    }
    
    public static King getInstance() {
        synchronized ("hello") {
            if (king == null) {
                king = new King();
            }
        }
        return king;
    }
}

當(dāng)然,無論是哪個(gè)線程在什么時(shí)候執(zhí)行以上代碼,都必須先“鎖住”代碼片斷后才能開始執(zhí)行,是沒有必要的,“鎖”的性能消耗是浪費(fèi)的,所以,可以進(jìn)一步調(diào)整為:

public class King {
    private static King king = null;
    
    private King() {
    }
    
    public static King getInstance() {
        if (king == null) { // 判斷有沒有必要鎖定接下來的代碼
            synchronized ("java") {
                if (king == null) { // 判斷有沒有必要?jiǎng)?chuàng)建對象
                    king = new King();
                }
            }
        }
        return king;
    }
}

至此,懶漢式的單例模式就完成了!

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多