回到首頁☞
Core子產品主要的功能是實作了反向控制IOC(Inversion of Control)與依賴注入DI(Dependency Injection)、Bean配置以及加載。Core子產品中有Beans、BeanFactory、BeanDefinitions、ApplicationContext等幾個重要概念。
Beans為Spring裡的各種對象,一般要配置在Spring配置檔案中:BeanFactory為建立Beans的Factory,Spring通過BeanFactory加載各種Beans;BeanDefinition為Bean在配置檔案中的定義,一般要定義id與class:ApplicationContext代表配置檔案。
這些類都位于org.springframework.beans和org.springframework.context中。這是Spring最核心的包。Core子產品依賴于Spring的Core類庫。

任何架構的核心是依賴關系,和資源有哪些是核心。
碼農都有一個問題,在實際項目中玩的很溜,因為架構都是搭建好的,一般一個系統出了前幾天搭建後續大家都是在自己的業務子產品開發。是以,0-1才是真正的核心。
1、整體了解
1.1、Core Container 核心容器
容器是Spring的核心部分,Core Container 子產品是Spring架構的基礎,所有子產品都建構于核心子產品之上。
- Beans : Beans子產品是所有應用都要用到的,它包含通路配置檔案、建立和管理bean以及進行Inversion of Control / Depen-dency Injection(IoC/DI)操作相關的所有類。
- Core : Core子產品主要包含Spring架構基本的核心工具類,Spring的其他元件要都要使用到這個包裡的類,Core子產品是其他元件的基本核心。當然你也可以在自己的應用系統中使用這些工具類。
- Context : Spring的上下文即IoC容器,通過上下文可以獲得容器中的Bean。 ApplicationContext接口是Context子產品的關鍵。 Context子產品建構于Core和Beans子產品基礎之上,提供了一種類似于JNDI注冊器的架構式的對象通路方法。
- SpEl : Expression Language子產品提供了一個強大的表達式語言用于在運作時查詢和操縱對象。
1.2、 Core Container 依賴關系
因為spring-core依賴了commons-logging,而其他子產品都依賴了spring-core,是以整個spring架構都依賴了commons-logging。
如依賴關系Spring離不開日志,但是日志架構有多種也不一定使用commons-logging如果有自己的日志實作如log4j,可以排除對commons-logging的依賴,沒有日志實作而排除了commons-logging依賴,編譯報錯。
1.3、建構最基礎的Spring項目
1.3.1、核心容器四個包
spring-beans-4.1.3.RELEASE.jar
spring-context-4.1.3.RELEASE.jar
spring-core-4.1.3.RELEASE.jar
spring-expression-4.1.3.RELEASE.jar
1.3.2、核心容器依賴的日志包
commons-logging-1.2.jar
log4j-1.2.17.jar
commons-logging相當于一個日志接口,log4j相當于該接口的實作,如果不添加log4j包也可以,因為commons-logging也有一個簡單的實作會自動使用。
1.3.3、測試類包
spring-test-4.1.3.RELEASE.jar
junit-4.10.jar(高于4.10版本還需要hamcrest-core.jar + hamcrest-library.jar)
1.3.4、測試類用到了AOP必須導入aop包
spring-aop-4.1.3.RELEASE.jar
1.3.5、pom
目前都是玩的Mavn,搜尋對應包就可以找到坐标
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>groupId</groupId>
<artifactId>myspring</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring-version>5.0.2.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<!-- Spring核心子產品 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring-version}</version>
<scope>test</scope>
</dependency>
<!-- 添加Log4J依賴 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.6.4</version>
</dependency>
</dependencies>
</project>
2、BeanFactory工廠
2.1、核心類圖
其實學習這個最好去讀下源碼,因為這個架構類之間層級結構比較深。
2.2、執行個體化BeanFactory
BeanFactory是執行個體化、配置、管理衆多Bean的容器。這些Bean類一般是離散的,但在Spring中被配置為互相依賴。BeanFactory根據配置執行個體化Bean對象,并設定互相的依賴性。
BeanFactory可用接口org.springframework.beans.factory.BeanFactory表示。BeanFactory有多種實作,最常用的為org.springframework.beans.factory.xml.XmlBeanFactory。XmlBeanFactory能加載XML格式的配置檔案。
執行個體化BeanFactory
在Web程式中使用者不需要執行個體化BeanFactory,Web程式加載的時候會自動執行個體化BeanFactory,并加載所有的Beans,将各種Bean設定到各個Servlet中、Struts的Action中、或者Hibernate資源中。開發者直接編寫Servlet、Action、Hibernate相關的代碼即可,無須操作 BeanFactory。
在Java桌面程式中,需要從BeanFactory中擷取Bean,是以需要執行個體化BeanFactory,構造函數的參數為配置檔案的路徑。例如加載ClassPath下的配置檔案可以用ClassPathResource加載,然後傳遞給XmlBeanFactory構造函數。代碼如下:
@Test
public void factoryTest(){
ClassPathResource resource = new ClassPathResource("applicationContext.xml");
XmlBeanFactory factory = new XmlBeanFactory(resource); // 擷取對象工廠
AdivceImpl adivce = (AdivceImpl) factory.getBean("proxyfactory");
adivce.doAny();
}
其實這個古老的方法,已經過期了,現在已經劃線不建議使用了。
使用ClassPathXmlApplicationContext 替代
@Test
public void factoryTest(){
BeanFactory container =
new ClassPathXmlApplicationContext("applicationContext.xml");
AdivceImpl adivce = (AdivceImpl) container.getBean("proxyfactory");
adivce.doAny();
}
參數applicationContext.xml為ClassPath根目錄下的檔案。applicationContext.xml為Spring預設的配置檔案名稱,預設存儲在ClassPath根目錄下。或者使用檔案流加載任意位置的配置檔案,并傳遞給XmlBeanFactory構造函數,例如:
@Test
public void factoryTest() throws FileNotFoundException {
String filePath ="D:\\workspace\\idea\\myspring\\src\\main\\resources\\ApplicationContext.xml";
Resource res = new FileSystemResource(filePath);
XmlBeanFactory container =new XmlBeanFactory(res);
AdivceImpl adivce = (AdivceImpl) container.getBean("proxyfactory");
adivce.doAny();
}
或者用ClassPathXmlApplicationContext加載多個配置檔案(多個配置檔案以字元串數組形式傳入),并傳遞給XmlBeanFactory構造函數:
ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml", "applicationContext-part2.xml"}); // 多個配置
BeanFactory factory = (BeanFactory)appContext; // ApplicationContext繼承自BeanFactory接口
2.3、XmlBeanFactory配置格式
一個BeanFactory中配置了多個Bean。在XmlBeanFactory中,配置檔案的根節點為< beans >,裡面定義了幾個< bean>子節點,每個< bean>定義一個Bean。格式如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans> <!-- Beans根節點 -->
<bean id="..." class="..."> <!--Bean節點,定義Bean-->
...
</bean>
<bean id="..." class="..."> <!--Bean節點,定義Bean-->
<property name="..." value="..."></property> <!-- Property定義屬性 -->
<property name="..." ref="..."></property> <!-- Property定義屬性 -->
</bean>
</beans>
3、配置Java Bean
一個BeanDefinition定義一個Bean,在XML中對應一個< bean >标記。Spring通過< bean >配置來執行個體化Bean,設定Bean的屬性,以及設定Bean之間互相的依賴性。
3.1、基本配置 < bean>
一個< bean >通常需要定義id與class屬性。class屬性是必須的,如果有其它Bean引用了該Bean,則id屬性是必須的。Bean之間通過id屬性互相通路,如:
<!--要增強的對象-->
<bean id="service" class="com.wht.service.impl.AdivceImpl"></bean>
上面代碼等價于
3.2、工廠模式factory-method
如果一個Bean不能通過new直接執行個體化,而是通過工廠類的某個方法建的,可以把class設為工廠類,用factory-method指向建立對象的法:
<!-- createInstance()是靜态方法 -->
<bean id="exampleBean"
class="example.MyFactoryBean"
factory-method="createInstance" />
<!-- createInstance()是非靜态方法 -->
<bean id="exampleBean2"
factory-bean="myFactoryBean"
factory-method="createInstance" />
3.3、構造函數< constructor-arg>
如果Bean的構造函數帶參數,那就需指定參數,用< constructor-arg>指定
<bean id="adivce" class="com.wht.service.impl.AdivceImpl">
<constructor-arg><value>Jack</value></constructor-arg>
<!-- 構造函數參數 -->
<constructor-arg><ref bean="anotherExampleBean" /></constructor-arg>
</bean>
每個的參數的順序要與構造函數相同。
3.4、單态模式singleton
Spring預設是單态模式,如果想使用非單例模式(稱為Prototype模式), scope=“prototype”:
<bean id="adivce" class="com.wht.service.impl.AdivceImpl" scope="prototype">
<constructor-arg><value>Jack</value></constructor-arg>
</bean>
非單例下,每次請求該Bean,都會生成一個新的對象。
3.5、配置屬性< property>
Spring通過Bean的setter方法設定屬性。是以,需要由Spring注射的屬性一般都具有公共的setter,getter方法。例如下面的配置代碼:
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://localhost:3306/dev?characterEncoding=UTF-8" />
<property name="username" value="dev" />
<property name="password" value="hcgk*2020" />
</bean>
destroy-method屬性配置關閉方法。在銷毀對象時會調用該方法。
注意:
<!-- 将password設為空字元串 -->
<property name="password"><value></value></property>
<!-- 将password設為null,也可以不設定 -->
<property name="password"><null /></property>
3.6、設定對象屬性< ref>
使用ref标簽配置Bean的id屬性使用。如:
<bean id="dao" class="com.wht.dao.impl.DaoImpl">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<bean class="com.wht.service.impl.ThreadServiceImpl">
<property name="dao" ref="dao"></property>
</bean>
ref的内容為引用的Bean的id屬性。
也可使用内部配置(或者内聯配置),類似于JAVA中的匿名類對象。因為内部配置一般不會被其他的Bean引用,是以不需要配置内部Bean的id。例如:
<property name="dao">
<bean class="example.DaoImpl"></bean>
</property>
除了使用< ref>的bean屬性,還可以使用local、parent,它們與bean屬性的作用是一樣的。不同的是,local隻能使用本配置檔案中的bean,而parent隻能使用父配置檔案中的bean,但bean則沒有任何限制。
3.7、配置List屬性< list>
< list>配置java.util.List類型的屬性。list屬性中可配置任意類型對象,如果為java對象,使用ref指定,或者< bean>定義新執行個體,如果是普通類型如String,int,double等,直接用字元串即可。< list>中的元素會按配置的先後順序排序,例如:
<property name="someList">
<list>
<value>String,Integer,Double,Boolean等類型對象</value>
<ref bean="myDataSource" />
</list>
</property>
3.8、配置Set屬性< set>
< set>配置java.util.Set類型的屬性。Set屬性中可配置任意類型對象。如果為java對象,則使用< ref>指定,或者使用< bean>重新定義新執行個體。如果是普通類型如String,int,double等,直接用字元串即可。例如:
<property name="someSet">
<set>
<value>String,Integer,Double,Boolean等類型對象</value>
<ref bean="myDataSource" />
<set>
</property>
3.9、配置Map屬性< map>
< map>配置java.util.Map類型的屬性。< entry>配置Map裡的元素,key指定索引,value指定值。如果為java對象,則使用ref指定,或者使用< bean>重新定義新執行個體,如果key為對象,,使用key-ref屬性,例如:
<property name="someMap">
<map>
<entry key="yup an entry">
<value>just some string</value>
</entry>
<entry key-ref="myDataSource">
<ref bean="serviceImpl" />
</entry>
</map>
</property>
3.10、配置Properties屬性< props>
這是真正項目常用的,但是對于大企業可能會提供統一的資源配置中心,通過SDK加密傳輸配置資訊。
使用< props>與< prop>配置Properties屬性。< props/>配置一個Properties對象,< prop/>配置一條屬性,屬性key配置索引,例如:
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">false</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
3.11、< idref>與< ref>的差別
< idref>與< ref>的作用是一樣的,都是配置java對象的。< idref>的用法也與< ref>基本相同。不同的是,< idref>隻有bean與local屬性,沒有parent屬性,如
Spring加載XML配置檔案時,會檢查< idref>配置的Bean存在不存在。而< ref>隻會在第一次調用時才會檢查。換句話說,如果Bean不存在,< idref>能在啟動程式的時候就抛出錯誤,而< ref>隻會在運作中抛出錯誤。
3.12、設定destory-method銷毀方法
有的對象(例如資料源,JDBC連接配接,輸入輸出流等)在使用完畢後需要執行close()方法釋放資源。可以使用destory-method配置。Spring在登出這些資源時會調用destory-method裡配置的方法。例如:
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
.....
</bean>
3.13、設定depends-on依賴對象
Spring預設按照配置檔案裡Bean配置的先後順序執行個體化Bean,但有時候在執行個體化A對象之前需要先執行個體化後面的B對象。這時候可以使用depends-on,強制先執行個體化B對象。如:
<bean id="a" class="examples.A" depends-on="b"></bean>
<bean id="b" class="examples.B"></bean>
在執行個體化A的時候會檢查B的執行個體是否存在,如果不存在,先執行個體化B
3.14、初始化方法init-method
與destory-method相反,有的對象在執行個體化後需要執行某些初始化代碼,但這些初始化代碼不能寫在構造函數中。這時候可以把這部分初始化代碼寫在一個方法中,如init(),使用init-method屬性,強制Spring執行該方法進行初始化,如:
4、屬性自動裝配autowire
為了防止配置檔案過大,可以使用autowire屬性
4.1、配置autowire自動裝配
使用< bean>的autowire屬性後,不需要再用< property name="" value="" />顯示地設定該Bean的屬性、依賴關系。Spring會根據反射,自動尋找符合條件的屬性,設定到該Bean屬性上。如果autowire設定為byType,将會按照屬性的類型自動比對。如:
4.2、autowire取值範圍
autowire屬性定義的不是需要自動裝配的屬性名,而是自動裝配的規則。一但配置,所有的屬性都将遵循autowire定義的規則。autowire所有的取值以及意義見下表
取值 | 說明 |
---|---|
no | (預設)不采用autowire機制.。這種情況,當我們需要使用依賴注入,隻能用< ref/>标簽。 |
byName | 通過屬性的名稱自動裝配(注入)。Spring會在容器中查找名稱與bean屬性名稱一緻的bean,并自動注入到bean屬性中。當然bean的屬性需要有setter方法。例如:bean A有個屬性master,master的setter方法就是setMaster,A設定了autowire=“byName”,那麼Spring就會在容器中查找名為master的bean通過setMaster方法注入到A中。 |
byType | 通過類型自動裝配(注入)。Spring會在容器中查找類(Class)與bean屬性類一緻的bean,并自動注入到bean屬性中,如果容器中包含多個這個類型的bean,Spring将抛出異常。如果沒有找到這個類型的bean,那麼注入動作将不會執行。 |
constructor | 類似于byType,但是是通過構造函數的參數類型來比對。假設bean A有構造函數A(B b, C c),那麼Spring會在容器中查找類型為B和C的bean通過構造函數A(B b, C c)注入到A中。與byType一樣,如果存在多個bean類型為B或者C,則會抛出異常。但時與byType不同的是,如果在容器中找不到比對的類的bean,将抛出異常,因為Spring無法調用構造函數執行個體化這個bean。 |
default | 采用父級标簽(即beans的default-autowire屬性)的配置。 |
如果顯示定義了< property>或者< constructor-arg>,會覆寫預設裝配。自動裝配一般與下面的依賴檢查連用。
注意:在大型項目中不推薦使用,因為自動裝配會隐藏依賴裝配的細節。降低可讀性與可維護性,并可能帶來意想不到的麻煩。
5、依賴檢查dependency
有時候某些Bean的屬性配置有錯誤,比如某個屬性沒有設定。這種錯誤在程式啟動的時候不會有任何異常表現,會一直潛伏到Spring調用該Bean時才會被發現。為了防止這種情況,Spring提供依賴檢查,在程式啟動的時候檢查依賴配置。如果有錯誤,啟動時就會抛出異常,以便發現配置錯誤。
5.1、配置dependency依賴檢查
依賴檢查能夠檢查屬性是否被設定。如果配置了依賴檢查,程式啟動時會進行配置校驗,以便及時地發現配置錯誤。通過設定的dependency-check設定依賴檢查規則,如:
5.2、dependency屬性取值範圍
dependency屬性有多種取值,分别應對不同的情況。但是需要注意,dependency依賴檢查是很生硬的,例如設定為object,将會檢查所有的java對象屬性,隻要有一個屬性沒有設定,就會抛出異常,即某屬性明明不需要設定,但是沒法避免dependency檢查,容易造成“一竿子全打死”的現象。dependency的取值以及意義見表
取值 | 說明 |
---|---|
no 或 default | 不做任何檢查 |
simple | 僅檢查基本類型,集合屬性。如果屬性沒有設定,會抛出異常。 |
object | 僅檢查Java對象屬性。如果有屬性沒設定,會抛出異常。 |
all | 檢查所有屬性,等同于simple與object的并集 |
6、Bean的進階特性
Spring程式中,JAVA Bean一般與Spring是非耦合的,不會依賴于Spring類庫。這也是Spring的優點。但有時候Java Bean需要知道自己在Spring架構中的一些屬性。Spring提供了一些接口,執行個體化Java Bean對象後Spring會調用接口的方法。
6.1、BeanNameAware接口擷取Bean的id
BeanNameAware接口幫助Java Bean知道自己在配置檔案中的id,實作BeanNameAware,實作方法名為setBeanName()方法,初始化該對象後Spring就會執行該回調方法,将id設定進來。Bean中設定一個變量,接受id名稱即可,例如:
package com.wht.spring.example;
import org.springframework.beans.factory.BeanNameAware;
public class WhatsTheNameBean implements BeanNameAware {
private String beanName;
public void setBeanName(String beanName) {
this.beanName = beanName;
}
}
提示:setBeanName()方法的回調發生在所有參數被設定完之後,初始化方法(init-method屬性)被執行之前。
6.2、BeanFactoryAware接口擷取BeanFactory
BeanFactoryAware接口幫助java Bean知道哪個BeanFactory執行個體化了自己,BeanFactoryAware接口中有setBeanFactory的回調方法,初始化該對象後,會回調該方法,将BeanFactory傳遞進來。BeanFactoryAware接口的代碼如下:
public interface BeanFactoryAware{
void setBeanFactory(BeanFactory beanFactory) throws BeanException
}
用法同BeanNameAware,實作了BeanFactoryAware接口的Java Bean能夠擷取到BeanFactory,從BeanFactory中能夠擷取到BeanFactory中配置的其他Java Bean。Spring不推薦這樣做,因為這樣會與Spring耦合。擷取其它Java Bean一般通過設定getter、setter方法,用依賴注入實作
6.3、InitializingBean接口執行初始化方法
實作了InitializingBean接口的Java Bean會在執行個體後、所有屬性被設定後調用初始化方法。但使用該接口會與Spring代碼發生耦合,是以不推薦使用。InitializingBean接口代碼如下:
public interface InitializingBean{
public void afterPropertiesSet();
}
Spring推薦使用init-method配置,效果等價:
6.4、BeanFactory進階特性
如果Java Bean實作了BeanFactoryAware接口,就能夠獲得BeanFactory對象。BeanFactory有下面幾個常用的方法如下,見名知意。
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String var1) throws BeansException;
<T> T getBean(String var1, @Nullable Class<T> var2) throws BeansException;
Object getBean(String var1, Object... var2) throws BeansException;
<T> T getBean(Class<T> var1) throws BeansException;
<T> T getBean(Class<T> var1, Object... var2) throws BeansException;
boolean containsBean(String var1);
boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String var1, @Nullable Class<?> var2) throws NoSuchBeanDefinitionException;
@Nullable
Class<?> getType(String var1) throws NoSuchBeanDefinitionException;
String[] getAliases(String var1);
7、屬性覆寫器
對于一些參數,更實用更簡單的方法是使用properties配置,而不是配置在Spring的配置檔案中。Spring提供屬性替代配置,允許把某些屬性配置在properties檔案中。
7.1、配置PropertyOverrideConfigurer屬性覆寫器
PropertyOverrideConfigurer允許把XML配置裡的某些參數配置到properties檔案中。這在資料庫配置中很常見。配置時需要配置一個PropertyOverrideConfigurer對象,指定properties檔案的位置,然後把替換的屬性用形如${jdbc.url}的字元串替代,如:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:jdbc.properties" />
</bean>
PropertyOverrideConfigurer對象會到指定名稱的properties檔案(例如jdbc.properties)中,尋找屬性名為變量的配置,{}中最好不要有空格
7.2、properties配置
具體的資料庫配置是寫在jdbc.properties裡面的。properties中的配置比applicationContext.xml中更便于閱讀、修改與維護。代碼如下:
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/dev?characterEncoding=UTF-8
jdbc.username=root
jdbc.password="admin
這個是目前真實性項目常用的方式,進一步說,這個配置還是在配置檔案中,而是通過SDK加載中央配置庫的加密配置。
回到首頁☞