摘要:目前建議使用與。入?yún)⑹钱斍罢谔幚淼?,是當前的配置名,返回的對象為處理后的。如果,則將放入容器的緩存池中,并返回。和這兩個接口,一般稱它們的實現(xiàn)類為后處理器。體系結(jié)構(gòu)讓容器擁有了發(fā)布應用上下文事件的功能,包括容器啟動事件關閉事件等。
點擊進入我的博客 1 如何理解IoC 1.1 依然是KFC的案例
interface Burger { int getPrice(); } interface Drink { int getPrice(); } class ZingerBurger implements Burger { public int getPrice() { return 10; } } class PepsiCola implements Drink { public int getPrice() { return 5; } } /** * 香辣雞腿堡套餐 */ class ZingerBurgerCombo { private Burger burger = new ZingerBurger(); private Drink drink = new PepsiCola(); public int getPrice() { return burger.getPrice() + drink.getPrice(); } }
上述案例中我們實現(xiàn)了一個香辣雞腿堡套餐,在ZingerBurgerCombo中,我們發(fā)現(xiàn)套餐與漢堡、套餐與飲品產(chǎn)生了直接的耦合。要知道肯德基中的套餐是非常多的,這樣需要建立大量不同套餐的類;而且如果該套餐中的百事可樂如果需要換成其他飲品的話,是不容易改變的。
class KFCCombo { private Burger burger; private Drink drink; public KFCCombo(Burger burger, Drink drink) { this.burger = burger; this.drink = drink; } } class KFCWaiter { public KFCCombo getZingerBurgerCombo() { return new KFCCombo(new ZingerBurger(), new PepsiCola()); } // else combo… }
為了防止套餐和漢堡、飲品的耦合,我們統(tǒng)一用KFCCombo來表示所有的套餐組合,引入了一個新的類KFCWaiter,讓她負責所有套餐的裝配。
1.2 控制反轉(zhuǎn)與依賴注入IoC的字面意思是控制反轉(zhuǎn),它包括兩部分的內(nèi)容:
控制:在上述案例中,控制就是選擇套餐中漢堡和飲品的控制權(quán)。
反轉(zhuǎn):反轉(zhuǎn)就是把該控制權(quán)從套餐本身中移除,放到專門的服務員手中。
對于Spring來說,我們通過Spring容器管理來管理和控制Bean的裝配。
由于IoC這個重要的概念比較晦澀隱諱,Martin Fowler提出了DI(Dependency Injection,依賴注入)的概念用以代替IoC,即讓調(diào)用類對某一接口實現(xiàn)類的依賴關系由第三方(容器或協(xié)作類)注入,以移除調(diào)用類對某一接口實現(xiàn)類的依賴。
Spring就是一個容器,它通過配置文件或注解描述類和類之間的依賴關系,自動完成類的初始化和依賴注入的工作。讓開發(fā)著可以從這些底層實現(xiàn)類的實例化、依賴關系裝配等工作中解脫出來,專注于更有意義的業(yè)務邏輯開發(fā)。
2 IoC的類型從注入方法上看,IoC可以分為:構(gòu)造函數(shù)注入、屬性注入、接口注入
class KFCCombo { private Burger burger; private Drink drink; // 在此注入對應的內(nèi)容 public KFCCombo(Burger burger, Drink drink) { this.burger = burger; this.drink = drink; } }
class KFCCombo { private Burger burger; private Drink drink; // 在此注入對應的內(nèi)容 public void setBurger(Burger burger) { this.burger = burger; } // 在此注入對應的內(nèi)容 public void setDrink(Drink drink) { this.drink = drink; } }
interface InjectFood { void injectBurger(Burger burger); void injectDrink(Drink drink); } class KFCCombo implements InjectFood { private Burger burger; private Drink drink; // 在此注入對應的內(nèi)容 public void injectBurger(Burger burger) { this.burger = burger; } // 在此注入對應的內(nèi)容 public void injectDrink(Drink drink) { this.drink = drink; } }
接口注入和屬性注入并無本質(zhì)的區(qū)別,而且還增加了一個額外的接口導致代碼增加,因此不推薦該方式。
3 資源訪問JDK提供的訪問資源的類(如java.net.URL、File等)并不能很好地滿足各種底層資源的訪問需求,比如缺少從類路徑或者Web容器上下文中獲取資源的操作類。因此,Spring提供了Resource接口,并由此裝載各種資源,包括配置文件、國際化屬性文件等資源。
3.1 Resource類圖WritableResource:可寫資源接口,Spring3.1新增的接口,有2個實現(xiàn)類:FileSystemResource和PathResource。
ByteArrayResource:二進制數(shù)組表示的資源,二進制數(shù)組資源可以在內(nèi)存中通過程序構(gòu)造。
ClassPathResource:類路徑下的資源,資源以相對于類路徑的方式表示。
FileSystemResouce:文件系統(tǒng)資源,資源以文件系統(tǒng)路徑的方式表示。
InputStreamResource:以輸入流返回標識的資源
ServletContextResource:為訪問Web容器上下文中的資源而設計的類,負責以相對于Web應用根目錄的路徑來加載資源。支持以流和URL的形式訪問,在war包解包的情況下,也可以通過File方式訪問。 該類還可以直接從JAR包中訪問資源。
UrlResource:封裝了java.net.URL,它使用戶能夠訪問任何可以通過URL表示的資源,如文件系統(tǒng)的資源、HTTP資源、FTP資源
PathResource:Spring 4.0提供的讀取資源文件的新類。PathResource封裝了java.net.URL、java.nio.file.Path、文件系統(tǒng)資源,它使用戶能夠訪問任何可以通過URL、Path、系統(tǒng)文件路徑標識的資源,如文件系統(tǒng)的資源、HTTP資源、FTP資源
3.2 資源加載為了訪問不同類型的資源,Resource接口下提供了不同的子類,這造成了使用上的不便。Spring提供了一個強大的加載資源的方式,在不顯示使用Resource實現(xiàn)類的情況下,僅通過不同資源地址的特殊標示就可以訪問對應的資源。
地址前綴 | 實例 | 釋義 |
---|---|---|
classpath: | classpath:com/ankeetc/spring/Main.class | 從類不經(jīng)中加載資源,classpath: 和 classpath:/ 是等價的,都是相對于類的根路徑,資源文件可以在標準的文件系統(tǒng)中,也可以在jar或者zip的類包中 |
file: | file:/Users/zhengzhaoxi/.gitconfig | 使用UrlResource從文件系統(tǒng)目錄中裝載資源,可以采用絕對路徑或者相對路徑 |
http:// | http://spiderlucas.github.io/... | 使用UrlResource從web服務器中加載資源 |
ftp:// | ftp://spiderlucas.github.io/atom.xml | 使用UrlResource從FTP服務器中裝載資源 |
沒有前綴 | com/ankeetc/spring/Main.class | 根據(jù)ApplicationContext的具體實現(xiàn)類采用對應類型的Resource |
假設有多個Jar包或者文件系統(tǒng)類路徑下?lián)碛幸粋€相同包名(如com.ankeetc):
classpath:只會在第一個加載的com.ankeetc包的類路徑下查找
classpath*:會掃描到所有的這些JAR包及類路徑下出現(xiàn)的com.ankeetc類路徑。
這對于分模塊打包的應用非常有用,假設一個應用分為2個模塊,每一個模塊對應一個配置文件,分別為module1.yaml 、module2.yaml,都放在了com.ankeetc的目錄下,每個模塊多帶帶打成JAR包??梢允褂?classpath*:com/ankeetc/module*.xml加載所有模塊的配置文件。
? 匹配文件名中的一個字符
* 匹配文件名中的任意字符
** 匹配多層路徑
ResourceLoader接口僅有一個getResource(String loacation)方法,可以根據(jù)一個資源地址加載文件資源。不過,資源地址僅支持帶資源類型前綴的表達式,不支持Ant風格的資源路徑表達式。
ResourcePatternResolver擴展ResourceLoader接口,定義了一個新的接口方法getResource(String locationPattern),改方法支持帶資源類型前綴及Ant風格的資源路徑表達式。
PathMatchingResourcePatternResolver是Spring提供的標準實現(xiàn)類。
4 BeanFactoryBeanFactory是Spring框架最核心的接口,它提供了高級IoC的配置機制。我們一般稱BeanFactory為IoC容器。
BeanFactory是Spring框架等基礎設施,面向Spring本身。
BeanFactory是一個類工廠,可以創(chuàng)建并管理各種類的對象。
所有可以被Spring容器實例化并管理的Java類都可以成為Bean。
BeanFactory主要方法就是getBean(String beanName);
BeanFactory啟動IoC容器時,并不會初始化配置文件中定義的Bean,初始化動作在第一個調(diào)用時產(chǎn)生。
對于單實例的Bean來說,BeanFactory會緩存Bean實例,在第二次使用geBean()獲取Bean時,將直接從IoC容器的緩存中獲取Bean實例。
4.1 BeanFactory體系結(jié)構(gòu)BeanFactory:BeanFactory接口位于類結(jié)構(gòu)樹的頂端,它最主要的方法就是getBean(String beanName) ,該方法從容器中返回特定名稱的Bean,BeanFactory的功能通過其他接口而得到不斷擴展。
ListableBeanFactory:該接口定義了訪問容器中Bean基本信息的若干方法,如:查看 Bean 的個數(shù)、獲取某一類型Bean的配置名、或查看容器中是否包含某一個Bean。
HierarhicalBeanFactory:父子級聯(lián) IoC 容器的接口,子容器可以通過接口方法訪問父容器。
ConfigurableBeanFactory:該接口增強了IoC容器的可定制性,它定義了設置類裝載器、屬性 編輯器、容器初始化后置處理器等方法。
AutowireCapableBeanFactory:定義了將容器中的Bean按某種規(guī)則(如:按名稱匹配、按類型匹配)進行自動裝配的方法。
SingletonBeanFactory:定義了允許在運行期間向容器注冊單實例Bean的方法。
BeanDefinitionRegistry:Spring配置文件中每一個Bean節(jié)點元素在Spring容器里都通過一個 BeanDefinition對象表示,它描述了Bean的配置信息。而BeanDefinitionRegistry接口提供了向容器手工注冊BeanDefinition對象的方法。
4.2 初始化BeanFactoryBeanFactory有多種實現(xiàn),最常用的是 XmlBeanFactory,但在Spring 3.2時已被廢棄。目前建議使用XmlBeanDefinitionReader與DefaultListableBeanFactory。
public static void main(String[] args) throws Exception { ResourceLoader resourceLoader = new DefaultResourceLoader(); Resource resource = resourceLoader.getResource("beans.xml"); DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory); reader.loadBeanDefinitions(resource); beanFactory.getBean(""); }4.3 BeanFactory中Bean的生命周期
當調(diào)用者通過getBean()向容器請求一個Bean時,如果容器注冊了InstantiationAwareBeanPostProcessor接口,則在實例化Bean之前,調(diào)用postProcessBeforeInstantiation()方法。
根據(jù)配置調(diào)用構(gòu)造方法或者工廠方法實例化Bean。
調(diào)用InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation()。
調(diào)用InstantiationAwareBeanPostProcessor#postProcessPropertyValues()方法。
設置屬性值。
如果Bean實現(xiàn)了BeanNameAware接口,則將調(diào)用BeanNameAware#setBeanName()接口方法,將配置文件中該Bean對應的名稱設置到Bean中。
如果Bean實現(xiàn)了BeanFactoryAware接口,將調(diào)用BeanFactoryAware#setBeanFactory()接口方法。
如果容器注冊了BeanPostProcessor接口,將調(diào)用BeanPostProcessor#postProcessBeforeInitialization()方法。入?yún)ean是當前正在處理的Bean,BeanName是當前Bean的配置名,返回的對象為處理后的Bean。BeanPostProcessor在Spring框架中占有重要的地位,為容器提供對Bean進行后續(xù)加工處理的切入點,AOP、動態(tài)代理都通過BeanPostProcessor來實現(xiàn)。
如果Bean實現(xiàn)了InitializingBean接口,則將調(diào)用InitializingBean#afterPropertiesSet()方法。
如果
調(diào)用BeanPostProcessor#postProcessAfterInitialization()方法再次加工Bean。
如果
對于scope="singleton"的Bean,當容器關閉時,將觸發(fā)Spring對Bean的后續(xù)生命周期的管理工作。如果Bean實現(xiàn)了DisposableBean接口,將調(diào)用DisposableBean#destroy()方法。
對于`scope="singleton"的Bean,如果通過
Bean自身的方法:構(gòu)造方法、Setter設置屬性值、init-method、destroy-method。
Bean級生命周期接口方法:如上圖中藍色的部分。BeanNameAware、BeanFactoryAware、InitializingBean、DisposableBean,這些由Bean本身直接實現(xiàn)。
容器級生命周期接口方法:如上圖中的紅色的部分。InstantiationAwareBeanPostProcessor和BeanPostProcessor這兩個接口,一般稱它們的實現(xiàn)類為后處理器。后處理器接口不由Bean本身實現(xiàn),實現(xiàn)類以容器附加裝置的形式注冊到Spring容器中。當Spring容器創(chuàng)建任何Bean的時候,這些后處理器都會起作用,所以這些后處理器的影響是全局的。如果需要多個后處理器,可以同時實現(xiàn)Ordered接口,容器將按照特定的順序依此調(diào)用這些后處理器。
工廠后處理器接口方法:AspectJWeavingEnabler、CustomAutowireConfigurer、ConfigurationClassPostProcessor等方法,工廠后處理器也是容器級的,在應用上下文裝配配置文件后立即使用。
4.4 BeanFactory生命周期案例public class Main { public static void main(String[] args) { Resource resource = new PathMatchingResourcePatternResolver().getResource("classpath:beans.xml"); DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory); reader.loadBeanDefinitions(resource); beanFactory.addBeanPostProcessor(new InstantiationAwareBeanPostProcessor() { public Object postProcessBeforeInstantiation(Class> beanClass, String beanName) throws BeansException { System.out.println("InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()"); return null; } public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { System.out.println("InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()"); return true; } public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { System.out.println("InstantiationAwareBeanPostProcessor.postProcessPropertyValues()"); return pvs; } public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("BeanPostProcessor.postProcessBeforeInitialization()"); return bean; } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("BeanPostProcessor.postProcessAfterInitialization()"); return bean; } }); MyBean myBean = beanFactory.getBean("myBean", MyBean.class); beanFactory.destroySingletons(); } } class MyBean implements BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean { private String prop; public MyBean() { System.out.println("MyBean:構(gòu)造方法"); } public String getProp() { System.out.println("MyBean:get方法"); return prop; } public void setProp(String prop) { System.out.println("MyBean:set方法"); this.prop = prop; } public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("MyBean:BeanFactoryAware.setBeanFactory()"); } public void setBeanName(String name) { System.out.println("MyBean:BeanNameAware.setBeanName()"); } public void destroy() throws Exception { System.out.println("MyBean:DisposableBean.destroy()"); } public void afterPropertiesSet() throws Exception { System.out.println("MyBean:InitializingBean.afterPropertiesSet()"); } // 配置文件中init-method public void myInit() { System.out.println("MyBean:myInit()"); } // 配置文件中destroy-method public void myDestroy() { System.out.println("MyBean:myDestroy()"); } }
4.5 關于Bean生命周期接口的探討
Bean生命周期帶來的耦合:通過實現(xiàn)Spring的Bean生命周期接口對Bean進行額外控制,雖然讓Bean具有了更細致的生命周期階段,但也帶來了一個問題,Bean和Spring框架緊密綁定在一起了,這和Spring一直推崇的“不對應用程序類作任何限制”的理念是相悖的。業(yè)務類本應該完全POJO化,只實現(xiàn)自己的業(yè)務接口,不需要和某個特定框架(包括Spring框架)的接口關聯(lián)。
init-method和destroy-method:可以通過
BeanPostProcessor:BeanPostProcessor接口不需要Bean去繼承它,可以像插件一樣注冊到Spring容器中,為容器提供額外功能。
5 ApplicationContext 5.1 Application體系結(jié)構(gòu)ApplicationEventPublisher:讓容器擁有了發(fā)布應用上下文事件的功能,包括容器啟動事件 、關閉事件等。實現(xiàn)了ApplicationListener事件監(jiān)聽接口的Bean可以接收到容器事件,并對容器事件進行響應處理。在ApplicationContext抽象實現(xiàn)類AbstractApplicationContext中存在一個 ApplicationEventMulticaster,它負責保存所有的監(jiān)聽器,以便在容器產(chǎn)生上下文事件時通知這些事件監(jiān)聽者。
MessageSource:為容器提供了i18n國際化信息訪問的功能。
ResourcePatternResolver:所有ApplicationContext實現(xiàn)類都實現(xiàn)了類似于PathMatchingResourcePatternResolver的功能,可以通過帶前綴 Ant 風格的資源類文件路徑來裝載Spring的配置文件。
LifeCycle:它提供了start()和stop()兩個方法,主要用于控制異步處理過程。在具體使用時,該接口同時被ApplicationContext實現(xiàn)及具體Bean實現(xiàn),ApplicationContext會將start/stop的信息傳遞給容器中所有實現(xiàn)了該接口的Bean,以達到管理和控制JMX、任務調(diào)度等目的。
ConfigurableApplicationContext:它擴展了ApplicationContext,讓ApplicationContext具有啟動、刷新和關閉應用上下文的能力。上下文關閉時,調(diào)用 refresh()即可啟動上下文;如果已經(jīng)啟動,則調(diào)用refresh()可清除緩存并重新加載配置信息;調(diào)用close()可關閉應用上下文。
5.2 初始化ApplicationContextClassPathXmlApplicationContext:從類路徑中加載XML配置文件,也可以顯示的使用帶資源類型前綴的路徑。
FileSystemXmlApplicationContext:從文件系統(tǒng)路徑下加載XML配置文件,也可以顯示的使用帶資源類型前綴的路徑。
AnnotationConfigApplicationContext:一個標注@Configuration注解的POJO即可提供Spring所需的Bean配置信息。
GenericGroovyApplicationContext:從Groovy配置中提取Bean。
public static void main(String[] args) throws Exception { ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("beans.xml"); FileSystemXmlApplicationContext fileSystemXmlApplicationContext = new FileSystemXmlApplicationContext("file:/Users/zhengzhaoxi/Git/spring/src/main/resources/beans.xml"); AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Config.class); }5.3 WebApplicationContext體系結(jié)構(gòu)
見后續(xù)章節(jié)
5.4 ApplicationContext中Bean的生命周期Bean在ApplicationContext和BeanFactory中生命周期類似,但有以下不同點
如果Bean實現(xiàn)了ApplicationContextAware接口,則會增加一個調(diào)用該接口方法的ApplicationContextAware.setApplicationContext的方法。
如果在配置文件中生命了工廠后處理器接口BeanFactoryPostProcessor的實現(xiàn)類,則應用上下文在裝在配置文件之后、初始化Bean實例之前會調(diào)用這些BeanFactoryPostProcessor對配置信息進行加工處理。Spring提供了多個工廠容器,如CustomEditorConfigure、PropertyPlaceholderConfigurer等。工廠后處理器是容器級的,只在應用上下文初始化時調(diào)用一次,其目的是完成一些配置文件加工處理工作。
ApplicationContext可以利用Java反射機制自動識別出配置文件中定義的BeanPostProcessor、InstantiationAwareBeanPostProcessor、BeanFactoryPostProcessor,并自動將它們注冊到應用上下文中(如下所示);而BeanFactory需要通過手工調(diào)用addBeanPostProcessor()方法注冊。
6 BeanFactory與ApplicationContext區(qū)別
一般稱BeanFactory為IoC容器:Bean工廠(com.springframework.beans.factory.BeanFactory)是Spring框架中最核心的接口,它提供了高級 IoC 的配置機制 。BeanFactory使管理不同類型的Java對象成為可能。BeanFactory是Spring框架的基礎設施,面向Spring本身。
一般稱ApplicationContext為應用上下文或Spring容器:應用上下文(com.springframework.context.ApplicationContext)建立在BeanFactory基礎之上,提供了更多面向應用的功能,它提供了國際化支持和框架事件體系,更易于創(chuàng)建實際應用 。 ApplicationContext 面向使用 Spring 框架的開發(fā)者,幾乎所有的應用場合都可以直接使用 ApplicationContext。
BeanFactory在初始化容器的時候,并未實例化Bean,直到第一次訪問某個Bean時才實例化Bean;ApplicationContext在初始化應用上下文的時候就實例化全部單實例Bean。
ApplicationContext可以利用Java反射機制自動識別出配置文件中定義的BeanPostProcessor、InstantiationAwareBeanPostProcessor、BeanFactoryPostProcessor,并自動將它們注冊到應用上下文中;而BeanFactory需要通過手工調(diào)用addBeanPostProcessor()方法注冊。
7 父子容器通過HierarchicalBeanFactory接口,Spring的IoC容器可以建立父子層級關聯(lián)的容器體系,子容器可以訪問父容器中的 Bean,但父容器不能訪問子容器的Bean。
在容器內(nèi),Bean的id必須是唯一的,但子容器可以擁有一個和父容器id相同的 Bean。
父子容器層級體系增強了Spring容器架構(gòu)的擴展性和靈活性,因此第三方可以通過編程的方式,為一個已經(jīng)存在的容器添加一個或多個特殊用途的子容器,以提供一些額外的功能。
Spring使用父子容器的特性實現(xiàn)了很多能力,比如在Spring MVC中,展現(xiàn)層Bean位于一個子容器中,而業(yè)務層和持久層的Bean位于父容器中。 這樣展現(xiàn)層Bean就可以引用業(yè)務層和持久層的Bean,而業(yè)務層和持久層的Bean則看不到展現(xiàn)層的Bean。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/72862.html
摘要:從使用到原理學習線程池關于線程池的使用,及原理分析分析角度新穎面向切面編程的基本用法基于注解的實現(xiàn)在軟件開發(fā)中,分散于應用中多出的功能被稱為橫切關注點如事務安全緩存等。 Java 程序媛手把手教你設計模式中的撩妹神技 -- 上篇 遇一人白首,擇一城終老,是多么美好的人生境界,她和他歷經(jīng)風雨慢慢變老,回首走過的點點滴滴,依然清楚的記得當初愛情萌芽的模樣…… Java 進階面試問題列表 -...
摘要:開啟自動配置功能后文詳解這個注解,學過的同學應該對它不會陌生,就是掃描注解,默認是掃描當前類下的。簡單來說,這個注解可以幫助我們自動載入應用程序所需要的所有默認配置。簡單理解這二者掃描的對象是不一樣的。 前言 只有光頭才能變強。 文本已收錄至我的GitHub倉庫,歡迎Star:https://github.com/ZhongFuCheng3y/3y 回顧前面Spring的文章(以學習...
摘要:學習總結(jié)學習整理的一些筆記,很簡單。大部分認為和只是不同的叫法而已。依賴注入的兩種方式和注解使用注釋驅(qū)動的功能源碼剖析 Spring IoC學習總結(jié) 學習spring Ioc整理的一些筆記,很簡單。分享給大家。 IoC 基本概念 在這之前,我們先記住一句話。好萊塢原則:Dont call us, we will call you.其實這句話很恰當?shù)匦稳萘朔崔D(zhuǎn)的意味;Ioc, Inve...
摘要:構(gòu)造函數(shù)注入通過調(diào)用類的構(gòu)造函數(shù),將接口實現(xiàn)類通過構(gòu)造函數(shù)變量傳入。而在中,其使用橫切技術(shù),將這類代碼從原屬的封裝對象中提取出來,封裝到一個可重用模塊中,稱為。 最近實習用到Spring的開發(fā)框架,但是之前沒有接觸過,因此希望利用網(wǎng)上的資源來學習以下。 Spring官方給出了非常全面的介紹,非常適合我這種完全的小白……在這一系列學習中,我閱讀的主要資源是5.1.2 Reference ...
閱讀 1613·2021-11-23 09:51
閱讀 1184·2019-08-30 13:57
閱讀 2264·2019-08-29 13:12
閱讀 2018·2019-08-26 13:57
閱讀 1202·2019-08-26 11:32
閱讀 981·2019-08-23 15:08
閱讀 708·2019-08-23 14:42
閱讀 3088·2019-08-23 11:41