什么是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ì)象都是“”獲取
new Object(),而IOC/DI出現(xiàn)之后我們由“”變?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í)的容器。比如:
國際化(MessageSource)
訪問資源,如URL和文件(ResourceLoader)
載入多個(gè)(有繼承關(guān)系)上下文 ,使得每一個(gè)上下文都專注于一個(gè)特定的層次,比如應(yīng)用的web層
消息發(fā)送、響應(yīng)機(jī)制(ApplicationEventPublisher)
Spring 有幾種配置方式?
- 基于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的常用注解