Spring的雜談上

什么是Spring框架?Spring框架有哪些主要的模塊?

??Spring框架是一個(gè)開放源代碼的J2EE應(yīng)用程序框架、是針對(duì)bean的生命周期進(jìn)行管理的輕量級(jí)容器。

??1.Spring框架是一個(gè)為J2EE的開發(fā)提供綜合、廣泛的基礎(chǔ)性支持的Java平臺(tái)。
??2.Spring幫助開發(fā)者解決了開發(fā)中的基礎(chǔ)問題,讓開發(fā)者可以專注于應(yīng)用程序的開發(fā)。
??3.Spring框架是非入侵式的框架,底層是依照設(shè)計(jì)模式精心打磨的框架,這讓我們可以在開發(fā)環(huán)境中安心的使用,無須操心Spring在后臺(tái)是如何工作的。
??4.Spring框架主要由七部分組成。如: Spring Core、 Spring AOP、 Spring ORM、 Spring DAO、Spring Context、 Spring Web和 Spring Web MVC,為我們開發(fā)提供了較多的腳手架。

使用Spring可以帶來哪些好處?

1.方便解耦,簡化開發(fā)
??Spring提供了IOC容器,讓對(duì)象之間的依賴關(guān)系由Spring進(jìn)行控制,避免了硬編碼帶來的過度耦合,使得用戶無需關(guān)心類的作用域、屬性文件解析的底層代碼,專注于上層應(yīng)用。

2.AOP編程的支持
??通過Spring的AOP功能,更方便的面向切面編程,使得有些功能在OOP層面難以做到,可以通過AOP輕松完成。

3.聲明式事務(wù)管理
??通過聲明式方式靈活地進(jìn)行事務(wù)的管理,將一些通用任務(wù)如安全、事務(wù)、日志等進(jìn)行集中式管理,提高開發(fā)效率和質(zhì)量。

4.方便程序測試
??Spring對(duì)Junit4支持,可以通過注解方便的測試Spring程序。

5.無縫集成各種優(yōu)秀框架
??Spring可以降低各種框架的使用難度,Spring提供了對(duì)各種優(yōu)秀框架(如ORM框架、LOGGING框架、Quartz)等的支持。

6.降低Java EE API的使用難度
??Spring對(duì)很多難用的Java EE API(如JDBC,JavaMail,遠(yuǎn)程調(diào)用等)提供了一個(gè)薄薄的封裝層,通過Spring的簡易封裝,這些Java EE API的使用難度大為降低。

7.Java 源碼是經(jīng)典學(xué)習(xí)范例
??提供了各種設(shè)計(jì)模式的實(shí)現(xiàn),讓我受益匪淺。

8.輕量級(jí)非入侵式
??與EJB容器相比較,IOC容器較為輕量級(jí),可以在節(jié)省內(nèi)存和CPU資源的消耗。

什么是IOC和DI?

IOC(Inversion Of Control) 控制反轉(zhuǎn):
??所謂的控制反轉(zhuǎn),就是把代碼里需要實(shí)現(xiàn)對(duì)象創(chuàng)建、依賴的代碼,反轉(zhuǎn)給容器來實(shí)現(xiàn)。

DI(Dependency Injection)依賴注入:
??對(duì)象被動(dòng)接受依賴類不需要自己實(shí)例或者尋找,簡單來說就是對(duì)象不是從容器中查找它依賴的類,而是在容器實(shí)例化對(duì)象的時(shí)候主動(dòng)將其依賴的類注入。

Java 中依賴注入哪三種實(shí)現(xiàn)方式?

??1.構(gòu)造器
??2.setter方法注入
??3.接口注入

請(qǐng)解釋下 Spring 框架中的 IOC?

??IOC的中文意思就是控制反轉(zhuǎn),就是把代碼里需要實(shí)現(xiàn)對(duì)象創(chuàng)建、依賴的代碼,反轉(zhuǎn)給容器來實(shí)現(xiàn)。

??IOC其實(shí)是一種編程思想的體現(xiàn),以往應(yīng)用程序獲取對(duì)象都是“\color{red}{主動(dòng)}”獲取new Object(),而IOC/DI出現(xiàn)之后我們由“\color{red}{主動(dòng)}”變?yōu)椤?img class="math-inline" src="https://math.jianshu.com/math?formula=%5Ccolor%7Bred%7D%7B%E8%A2%AB%E5%8A%A8%7D" alt="\color{red}{被動(dòng)}" mathimg="1">”,所有需要注入的對(duì)象由IOC/DI進(jìn)行注入。

具體是怎么實(shí)現(xiàn)的呢?

??IOC本質(zhì)上是一個(gè)容器,用于存儲(chǔ)所有被Spring管理的Bean。

具體實(shí)現(xiàn):
??這個(gè)要從IOC容器初始化去一步一步了解,IOC初始化會(huì)經(jīng)歷三個(gè)步驟,定位、加載、注冊三步。

定位階段(我們知道 Bean是由Spring IOC容器中存儲(chǔ)的吧,可是我去哪里找這些Bean呢?對(duì)象和對(duì)象的關(guān)系如何表示?這個(gè)時(shí)候需要我們告訴Spring 我們需要被管理的類在哪里?)

??描述對(duì)象之間的關(guān)系文件一般是:yml、xml、properties等。

??描述對(duì)象關(guān)系文件一般存儲(chǔ)在:classpath、filesystem、URL網(wǎng)絡(luò)資源、servletContext等。

??例如是 xml文件的讀取,通過ApplicationContext context = new ClassPathXmlApplicationContext(“application.xml”);告訴Spring 描述對(duì)象之間關(guān)系的文件在這里,Spring表示知道了文件的地方然后調(diào)用setConfigLocations(configLocations);方法解析Bean定義資源文件的路徑,然后調(diào)用AbstractApplicationContext.refresh()方法。

加載階段 (Spring現(xiàn)在知道了,需要被管理的類在哪個(gè)地方了,可是IOC還沒有進(jìn)行初始化,什么時(shí)候進(jìn)行呢?Bean描述對(duì)象關(guān)系的內(nèi)容被存儲(chǔ)在哪里呢?然后Bean文件怎么被讀取呢?)

??AbstractApplicationContext.refresh()里調(diào)用方法ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 這里獲得一個(gè)BeanFactroy工廠,IOC容器在這里完成了初始化。有人會(huì)問了,BeanFactory就是IOC容器嗎?我可以告訴你,是的,里面包含了存儲(chǔ)Bean的容器。
??現(xiàn)在我們的IOC容器初始化完成,這個(gè)時(shí)候需要對(duì)xml配置的bean描述文件進(jìn)行加載,在Spring中,所有的描述對(duì)象關(guān)系的文件都會(huì)被保存為BeanDefinition,在obtainFreshBeanFactory()真正的實(shí)現(xiàn)類里會(huì)調(diào)用AbstractXmlApplicationContext.loadBeanDefinitions(beanFactory);方法去載入。
??用什么去讀取xml文件呢?使用InputStream 使用文件IO流讀入將XML文件轉(zhuǎn)換為DOM對(duì)象,解析過程由doLoadDocument(inputSource, resource);實(shí)現(xiàn)。主要這個(gè)DOM對(duì)象不是Spring內(nèi)部的DOM對(duì)象,得到這個(gè)DOM之后,還要繼續(xù)去調(diào)用子類,按照Spring的Bean語義要求將Bean定義資源解析并轉(zhuǎn)換為容器內(nèi)部數(shù)據(jù)結(jié)構(gòu),具體調(diào)用registerBeanDefinitions(Document doc, Resource resource);進(jìn)行Bean 的加載,(這個(gè)時(shí)候還沒有進(jìn)行注冊/初始化)。

注冊階段(我們的Bean是怎么被解析的,被誰解析,被注冊成什么了?)

??我們的bean文件,具體是被BeanDefinitionParserDelegate進(jìn)行解析,具體是怎么樣的呢,在加載階段獲得的DOM對(duì)象獲取到具體需要被掃描的Bean的文件路徑,然后通過文件流的方式進(jìn)行讀取解析。
??解析的過程非常復(fù)雜,我就不去深究了,解析完成的得到BeanDefinition,通過BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());向IOC容器注冊解析Bean,最后得到beanDefinitionMap。

BeanFactory和ApplicationContext的區(qū)別?

??BeanFactory可以理解為含有bean集合的工廠類。BeanFactory包含了各種bean的定義,可以滿足客戶端請(qǐng)求對(duì)應(yīng)的bean。

??ApplicationContext接口繼承了ListableBeanFactory而ListableBeanFactory是BeanFactroy的具體實(shí)現(xiàn),也就是說ApplicationContext里擁有了BeanFactory的功能。

??Spring中,ApplicationContext擁有了比BeanFactroy更多的功能,是一個(gè)更加高級(jí)的容器。比如:

  1. 國際化(MessageSource)

  2. 訪問資源,如URL和文件(ResourceLoader)

  3. 載入多個(gè)(有繼承關(guān)系)上下文 ,使得每一個(gè)上下文都專注于一個(gè)特定的層次,比如應(yīng)用的web層

  4. 消息發(fā)送、響應(yīng)機(jī)制(ApplicationEventPublisher)

Spring 有幾種配置方式?

  1. 基于XML的配置 2. 基于注解的配置 3. 基于Java的配置

如何使用xml來配置Spring框架?

目的

??SpringXML 配置的主要目的是使得所有的Spring組件都可以通過XML文件進(jìn)行配置。

配置方式

??Spring的XML配置方式是使用命名空間所支持的XML標(biāo)簽來實(shí)現(xiàn)的
??Spring 有以下主要幾個(gè)命名空間和組件:
????context、beans、jdbc、tx、aop、mvc 、aso

??下面這個(gè)web.xml,配置了DispatcherServlet,這件最簡單的配置便能滿足應(yīng)用程序配置運(yùn)行時(shí)組件的需求。


    <web-app>
        <display-name>Archetype Created Web Application</display-name>
        <servlet>
        <servlet-name>spring</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
                    </servlet-class>
        <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
        <servlet-name>spring</servlet-name>
        <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>

如何通過Java配置的方式配置Spring?

??Spring對(duì)Java配置可以通過注解@Configuration@Bean來完成的。

@Bean

??@Bean 標(biāo)識(shí)一個(gè)用于配置和初始化一個(gè)由SpringIOC容器管理的新對(duì)象的方法,類似于XML配置文件的<bean/>,一般與@Configration注解配合使用

@Configuration

??@Configuration用于定義配置類,可替換xml配置文件,被注解的類內(nèi)部包含有一個(gè)或多個(gè)被@Bean注解的方法,這些方法將會(huì)被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext類進(jìn)行掃描,并用于構(gòu)建bean定義,初始化Spring容器。

需要注意!需要注意! 需要注意!

@Configuration不可以是final類型;

@Configuration不可以是匿名類;

嵌套的configuration必須是靜態(tài)類。

@Configuration
public class AppConfig{
    @Bean
    public MyService myService() {
        return new MyServiceImpl();
    }
}
<beans>
        <bean id="myService" class="com.gupaoedu.services.MyServiceImpl"/>
</beans>

上述配置方式的實(shí)例化方式如下:利用 AnnotationConfigApplicationContext 類進(jìn)行實(shí)例化

    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        MyService myService = ctx.getBean(MyService.class);
        myService.doStuff();
    }

要使用組件組建掃描,僅需用@Configuration 進(jìn)行注解即可:

    @Configuration
    @ComponentScan(basePackages = "com.dia")
    public class AppConfig {

    }

??在上面的例子中,com.dia 包首先會(huì)被掃到,然后再容器內(nèi)查找被@Component 聲明的類,找到后將這些類按照 Sring bean 定義進(jìn)行注冊。

??如果你要在web應(yīng)用開發(fā)中選中上述的配置方式,需要用AnnotationConfigWebApplicationContext 類來讀取配置文件,可以用來配置 Spring 的Servlet 監(jiān)聽器 ContrextLoaderListener 或者 Spring MVC 的 DispatcherServlet。


<web-app>
    <!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext
        instead of the default XmlWebApplicationContext -->
    <context-param>
    <param-name>contextClass</param-name>
    <param-value>
        org.springframework.web.context.support.AnnotationConfigWebApplicationContext
                </param-value>
    </context-param>
    
    <!-- Configuration locations must consist of one or more comma- or space-delimited
        fully-qualified @Configuration classes. Fully-qualified packages may also be
        specified for component-scanning -->
    <context-param>
    
    
    <param-name>contextConfigLocation</param-name>
    
    <param-value>com.gupaoedu.AppConfig</param-value>
    </context-param>
    <!-- Bootstrap the root application context as usual using ContextLoaderListener -->
    <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
    <!-- Declare a Spring MVC DispatcherServlet as usual -->
    <servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext
        instead of the default XmlWebApplicationContext -->
    <init-param>
    
    <param-name>contextClass</param-name>
    
    <param-value>
        org.springframework.web.context.support.AnnotationConfigWebApplicationContext
                </param-value>
    </init-param>
    
    <!-- Again, config locations must consist of one or more comma- or space-delimited
        and fully-qualified @Configuration classes -->
    <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>com.gupaoedu.web.MVCConfig</param-value>
    </init-param>
    </servlet>
    
    <!-- map all requests for /web/* to the dispatcher servlet -->
    <servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/web/*</url-pattern>
    </servlet-mapping>

</web-app>

用注解的方式配置 Spring?

??Spring在2.5版本后支持注解方式,可使用注解替代XML。注解裝配在 Spring 中是默認(rèn)關(guān)閉的。如果你想要在你的應(yīng)用程序中使用關(guān)于注解的方法的話,請(qǐng)參考如下的配置:

    <beans>
        <context:annotation-config/>
        <!-- bean definitions go here -->
    </beans>

在標(biāo)簽配置完成以后,就可以用注解的方式在 Spring 中向?qū)傩?、方法和?gòu)造方法中自動(dòng)裝配變量。

如果有興趣可以去看看 Spring的常用注解

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容