介紹下什么是Spring?
Spring是一個輕量級Java開發(fā)框架,最早有Rod Johnson創(chuàng)建,目的是為了解決企業(yè)級應(yīng)用開發(fā)的業(yè)務(wù)邏輯層和其他各層的耦合問題。它是一個分層的JavaSE/JavaEE full-stack (一站式)輕量級開源框架,為開發(fā)Java應(yīng)用程序提供全面的基礎(chǔ)架構(gòu)支持。Spring負(fù)責(zé)基礎(chǔ)架構(gòu),因此Java開發(fā)者可以專注于應(yīng)用程序的開發(fā)。
Spring最根本的使命是解決企業(yè)級應(yīng)用開發(fā)的復(fù)雜性,即簡化Java開發(fā)。
Spring可以做很多事情,它為企業(yè)級開發(fā)提供給了豐富的功能,但是這些功能的底層都依賴于它的兩個核心特性,也就是依賴注入(dependency injection,DI) *和 *面向切面編程(aspect-oriented programming,AOP)。
為了降低Java開發(fā)的復(fù)雜性,Spring采取了以下4種關(guān)鍵策略·
基于POJO的輕量級和最小侵入性編程;
通過依賴注入和面向接口實現(xiàn)松耦合;
基于切面和慣例進行聲明式編程;
通過切面和模板減少樣板式代碼。
Spring框架都有哪些特點?
輕量級
從大小與開銷兩方面而言Spring都是輕量的。完整的Spring框架可以在一個大小只有1M多的JAR文件里發(fā)布,并且Spring所需的處理開銷也是微不足道的。
此外,Spring是非侵入式的∶典型的,Spring應(yīng)用中的對象不依賴于Spring的特定類。
控制反轉(zhuǎn)
Spring通過一種稱作控制反轉(zhuǎn)IOC的技術(shù)促進了低耦合。
當(dāng)應(yīng)用了IOC,一個對象依賴的其他對象會通過被動的方式傳遞進來,而不是這個對象自己創(chuàng)建或者查找依賴對象。
面向切面
Spring支持面向切面的編程,并且把應(yīng)用業(yè)務(wù)邏輯和系統(tǒng)服務(wù)分開
容器
Spring包含并管理應(yīng)用對象的配置和生命周期,在這個意義上它是一種容器,你可以配置你的每個bean如何被創(chuàng)建(基于一個可配置原型,你的bean可以創(chuàng)建一個單獨的實例或者每次需要時都生成—個新的實例)以及它們是如何相互關(guān)聯(lián)的。
框架集合
Spring可以將簡單的組件配置、組合成為復(fù)雜的應(yīng)用。
在Spring中,應(yīng)用對象被聲明式地組合,典型的是在一個XML文件里。
Spring也提供了很多基礎(chǔ)功能(事務(wù)管理、持久化框架集成等),將應(yīng)用邏輯的開發(fā)留給開發(fā)者。
Spring由哪些模塊組成?(列舉?些重要的Spring模塊?)
Spring總共大約有20個模塊,由1300多個不同的文件構(gòu)成。而這些組件被分別整合在核心容器(Core container) 、AOP(Aspect oriented Programming)和設(shè)備支持(Instrmentation).數(shù)據(jù)訪問與集成(Data Access/Integeration)、web、消息(Messaging)、Test等6個模塊中。以下是Spring 4的模塊結(jié)構(gòu)圖:

常用模塊(重要模塊):
Spring Core:提供了框架的基本組成部分,包括控制反轉(zhuǎn)(Inversion of Control,IOC)和依賴注入(Dependency Injection,DI)功能。
Spring Beans:提供了BeanFactory,是工廠模式的一個經(jīng)典實現(xiàn),Spring將管理對象稱為Bean。
Spring Context:構(gòu)建于core封裝包基礎(chǔ)上的context封裝包,提供了一種框架式的對象訪問方法。
SpringJDBC:提供了一個JDBC的抽象層,消除了煩瑣的JDBC編碼和數(shù)據(jù)庫廠商特有的錯誤代碼解析,用于簡化JDBC。
Spring ROM: Spring框架插入了若千個 ORM框架,從而提供了ORM的對象關(guān)系工具,其中包括JDO、 Hibernate和Batis SQL Map。所有這些都遭從Spring 的通用事務(wù)和DAO異棠層次結(jié)構(gòu)。
SpringAOP:提供了面向切面的編程實現(xiàn),讓你可以自定義攔截器、切點等。
SpringWeb:提供了針對Web開發(fā)的集成特性,例如文件上傳,利用servlet listeners進行ioc容器初始化和針對Web的ApplicationContext。
SpringTest:主要為測試提供支持的,支持使用JUnit或TestNG對Spring組件進行單元測試和集成測試。
Spring框架用到了哪些設(shè)計模式?
工廠模式: BeanFactory就是簡單工廠模式的體現(xiàn),用來創(chuàng)建對象的實例;
單例模式: Bean默認(rèn)為單例模式。
代理模式: Spring的AOP功能用到了JDK的動態(tài)代理和CGLIB字節(jié)碼生成技術(shù);
適配器模式: Spring AOP 的增強或通知(Advice)使?到了適配器模式、spring MVC 中也是?到了適配器模式適配 Controller 。
模板方法: 用來解決代碼重復(fù)的問題。比如.RestTemplate, JmsTemplate, JpaTemplate。
觀察者模式:定義對象鍵一種一對多的依賴關(guān)系,當(dāng)一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都會得到通知被制動更新,如Spring中l(wèi)istener的實現(xiàn)-ApplicationListener。
包裝器設(shè)計模式 : 我們的項?需要連接多個數(shù)據(jù)庫,?且不同的客戶在每次訪問中根據(jù)需要會去訪問不同的數(shù)據(jù)庫。這種模式讓我們可以根據(jù)客戶的需求能夠動態(tài)切換不同的數(shù)據(jù)源。
Spring IOC & AOP
什么是IOC容器?
IOC(Inversion of Control)即控制反轉(zhuǎn)是一種設(shè)計思想,它把傳統(tǒng)上由程序代碼直接操控的對象的調(diào)用權(quán)交給容器,通過容器來實現(xiàn)對象組件的裝配和管理。所謂的”控制反轉(zhuǎn)”概念就是對組件對象控制權(quán)的轉(zhuǎn)移,從程序代碼本身轉(zhuǎn)移到了外部容器。
Spring lOC負(fù)責(zé)創(chuàng)建對象,管理對象(通過依賴注入(DI),裝配對象,配置對象,并且管理這些對象的整個生命周期。
IoC 容器實際上就是個Map(key, value) ,Map 中存放的是各種對象。
什么是依賴注入?
依賴注入:相對于loC而言,依賴注入(DI)更加準(zhǔn)確地描述了loC的設(shè)計理念。所謂依賴注入
(Dependency Injection),即組件之間的依賴關(guān)系由容器在應(yīng)用系統(tǒng)運行期來決定,也就是由容器動態(tài)地將某種依賴關(guān)系的目標(biāo)對象實例注入到應(yīng)用系統(tǒng)中的各個關(guān)聯(lián)的組件之中。組件不做定位查詢,只提供普通的Java方法讓容器去決定依賴關(guān)系??偨Y(jié):依賴于容器的注入對象
SpringBean的作用域?
Spring應(yīng)用上下文中所有bean默認(rèn)都是作為singleton(單例),不管bean被注入多少次都是同一個實例。
Spring的Bean 定義了 5 種作用域 : 分別為 singleton(單例)、prototype(原型)、
request、session 和 global session
Singleton:單例模式(多線程下不安全)
Spring IoC 容器中只會存在一個共享的 Bean 實例,無論有多少個
Bean 引用它,始終指向同一對象。該模式在多線程下是不安全的。Singleton 作用域是Spring 中的缺省作用域,也可以顯示的將 Bean 定義為 singleton 模式,配置為:
|
<bean id="userDao" class="com.ioc.UserDaoImpl" scope="singleton"/>
|
Prototype:原型模式(每次使用時創(chuàng)建)
每次通過 Spring 容器獲取 prototype 定義的 bean 時,容器都將創(chuàng)建一個新的 Bean 實例,每個 Bean 實例都有自己的屬性和狀態(tài),而 singleton 全局只有一個對象。根據(jù)經(jīng)驗,對有狀態(tài)的 bean 使用 prototype 作用域,而對無狀態(tài)的 bean 使用 singleton作用域。
Request(一個request一個實例):
在一次 Http 請求中,容器會返回該 Bean 的同一實例。而對不同的 Http 請求則會產(chǎn)生新的 Bean,而且該 bean 僅在當(dāng)前 Http Request 內(nèi)有效,當(dāng)前 Http 請求結(jié)束,該 bean實例也將會被銷毀。
|
<bean id="loginAction" class="com.cnblogs.Login" scope="request"/>
|
Session:
在一次 Http Session 中,容器會返回該 Bean 的同一實例。而對不同的 Session 請
求則會創(chuàng)建新的實例,該 bean 實例僅在當(dāng)前 Session 內(nèi)有效。同 Http 請求相同,每一次session 請求創(chuàng)建新的實例,而不同的實例之間不共享屬性,且實例僅在自己的 session 請求內(nèi)有效,請求結(jié)束,則實例將被銷毀。
|
<bean id="userPreference" class="com.ioc.UserPreference" scope="session"/>
|
Global Session
在一個全局的 Http Session 中,容器會返回該 Bean 的同一個實例,僅在
使用 portlet context 時有效。
注意:缺省的Spring bean的作用域是Singleton。使用prototype作用域需要慎重的思考,因為頻繁創(chuàng)建和銷毀bean 會帶來很大的性能開銷。
你怎么定義Bean(類)的作用域?
當(dāng)定義一個在Spring里,我們還能給這個bean聲明一個作用域。它可以通過bean定義中的scope屬性來定義。如,當(dāng)Spring要在需要的時候每次生產(chǎn)一個新的bean實例,bean的scope屬性被指定為prototype。另一方面,一個bean每次使用的時候必須返回同一個實例,這個bean的scope屬性必須設(shè)為singleton。
Spring 中的單例 bean 的線程安全問題了解嗎?(為什么單例模式線程不安全?)
單例 bean 存在線程問題,主要是因為當(dāng)多個線程操作同?個對象的時候,對這個對象的?靜態(tài)成員變量的寫操作會存在線程安全問題。
實際上大部分時候spring bean無狀態(tài)的(比如dao類),所有某種程度上來說bean也是安全的,但如果bean 有狀態(tài)的話(比如view model對象),那就要開發(fā)者自己去保證線程安全了,最簡單的就是改變bean 的作用域,把"singleton"變更為"prototype”,這樣請求bean相當(dāng)于new Bean()了,所以就可以保證線程安全了。
·有狀態(tài)就是有數(shù)據(jù)存儲功能?!o狀態(tài)就是不會保存數(shù)據(jù)。
常見的兩種解決方式:
1. 在Bean對象中盡量避免定義可變的成員變量(不太現(xiàn)實)。
2. 在類中定義?個ThreadLocal成員變量,將需要的可變成員變量保存在 ThreadLocal 中(推薦的?種?式)。
Spring Bean 生命周期
實例化
- 實例化一個Bean,就是new 一個對象
IOC依賴注入
- 按照Spring上下文對實例化的Bean進行配置,也就是IOC注入。
setBeanName
- 如果 Bean 實現(xiàn)了 BeanNameAware 接?,調(diào)? setBeanName() ?法,傳?Bean的名字。
BeanFactoryAware 實現(xiàn)
- 如果Bean 實現(xiàn)了 BeanFactoryAware 接口,會調(diào)用它實現(xiàn)的 setBeanFactory()方法。
ApplicationContextAware 實現(xiàn)
- 如果Bean實現(xiàn)了ApplicationContextAware接口,會調(diào)用setApplicationContext(ApplicationContext)方法,傳入 Spring 上下文(同樣這個方式也可以實現(xiàn)步驟 4 的內(nèi)容,但比 4 更好,因為 ApplicationContext 是 BeanFactory 的子接口,有更多的實現(xiàn)方法)
postProcessBeforelnitialization接口實現(xiàn)-初始化預(yù)處理
- 如果Bean關(guān)聯(lián)了BeanPostProcessor接口,將會調(diào)用postProcessBeforeInitialization(Object obj, String s)方法,BeanPostProcessor 經(jīng)常被用作是 Bean 內(nèi)容的更改,并且由于這個是在 Bean 初始化結(jié)束時調(diào)用那個的方法,也可以被應(yīng)用于內(nèi)存或緩存技術(shù)。
init-method
- 如果 Bean 在 Spring 配置文件中配置了 init-method 屬性會自動調(diào)用其配置的初始化方法。
postProcessAfterInitialization
- 如果Bean關(guān)聯(lián)了BeanPostProcessor接口,將會調(diào)用postProcessAfterInitialization(Object obj, String s)方法。
注:以上工作完成以后就可以應(yīng)用這個 Bean 了,那這個 Bean 是一個 Singleton 的,所以一般情況下我們調(diào)用同一個 id 的 Bean 會是在內(nèi)容地址相同的實例,當(dāng)然在 Spring 配置文件中也可以配置非 Singleton。
Destroy過期自動清理階段
- 當(dāng)要銷毀 Bean 的時候,如果 Bean 實現(xiàn)了 DisposableBean 接?,執(zhí)? destroy() ?法
destroy-method自配置清理
- 當(dāng)要銷毀 Bean 的時候,如果 Bean 在配置?件中的定義包含 destroy-method 屬性,執(zhí)?指定的?法。

BeanFactory和FactoryBean的區(qū)別?
BeanFactory:是一個工廠,IOC的頂級接口(其實是構(gòu)建了一個spring上下文的環(huán)境,容器),用來管理和獲取Bean對象。
FactoryBean:是一個Bean生成工具,是用來獲取一種類型對象的Bean,它是構(gòu)造Bean實例的一種方式。用戶可以通過實現(xiàn)該接口定制實例化Bean的邏輯。
Spring 依賴注入的方式?
4種:構(gòu)造器注入、setter方法注入、靜態(tài)工廠注入、實例工廠注入
構(gòu)造器依賴注入:構(gòu)造器依賴注入通過容器觸發(fā)一個類的構(gòu)造器來實現(xiàn)的,該類有一系列參數(shù),每個參數(shù)代表一個對其他類的依賴。
Setter方法注入: Setter方法注入是容器通過調(diào)用無參構(gòu)造器或無參static工廠方法實例化bean之后,調(diào)用該bean的setter方法,即實現(xiàn)了基于setter的依賴注入。
**靜態(tài)工廠注入: **通過調(diào)用靜態(tài)工廠的方法來獲取自己需要的對象,為了讓 spring 管理所有對象,我們不能直接通過"工程類.靜態(tài)方法()"來獲取對象,而是依然通過 spring 注入的形式獲取。
實例工廠注入: 獲取對象實例的方法不是靜態(tài)的,所以你需要首先 new 工廠類,再調(diào)用普通的實例方法。
最常用的是構(gòu)造器和setter方式的注入。
兩者區(qū)別:

兩種依賴方式都可以使用,構(gòu)造器注入和Setter方法注入。最好的解決方案是用構(gòu)造器參數(shù)實現(xiàn)強制依賴,setter方法實現(xiàn)可選依賴。
什么是Bean的裝配?
裝配,或bean裝配是指在Spring容器中把bean組裝到一起,前提是容器需要知道bean的依賴關(guān)系,如何通過依賴注入來把它們裝配到一起。
什么是bean的自動裝配?
在Spring框架中,在配置文件中設(shè)定bean的依賴關(guān)系是一個很好的機制,Spring容器能夠自動裝配相互合作的bean,這意味著容器不需要和配置,能通過Bean工廠自動處理bean之間的協(xié)作。這意味著Spring可以通過向Bean Factory中注入的方式自動搞定bean之間的依賴關(guān)系。自動裝配可以設(shè)置在每個bean上,也可以設(shè)定在特定的bean上。
解釋不同方式的自動裝配,spring自動裝配bean有哪些方式?
在spring中,對象無需自己查找或創(chuàng)建與其關(guān)聯(lián)的其他對象,由容器負(fù)責(zé)把需要相互協(xié)作的對象引用賦予各個對象,使用autowire來配置自動裝載模式。
在Spring框架xml配置中共有5種自動裝配:
no: 默認(rèn)的方式是不進行自動裝配的,通過手工設(shè)置ref屬性來進行裝配bean。
byName:通過bean的名稱進行自動裝配,如果一個bean的property與另一bean的name相同,就進行自動裝配。
byType:通過參數(shù)的數(shù)據(jù)類型進行自動裝配。
constructor:利用構(gòu)造函數(shù)進行裝配,并且構(gòu)造函數(shù)的參數(shù)通過byType進行裝配。
autodetect:自動探測,如果有構(gòu)造方法,通過construct的方式自動裝配,否則使用byType的方式自動裝配。
使用@Autowired注解自動裝配的過程是怎樣的?
使用@Autowired注解來自動裝配指定的bean。
在使用@Autowired注解之前需要在Spring配置文件進行配置,<context:annotation-config />。
在啟動spring loC時,容器自動裝載了一個AutowiredAnnotationBeanPostProcessor后置處理器,當(dāng)容器掃描到@Autowied、@Resource或@Inject時,就會在IOC容器自動查找需要的bean,并裝配給該對象的屬性。在使用@Autowired時,首先在容器中查詢對應(yīng)類型的bean:
如果查詢結(jié)果剛好為一個,就將該bean裝配給@Autowired指定的數(shù)據(jù);·
如果查詢的結(jié)果不止一個,那么@Autowired會根據(jù)名稱來查找;
如果上述查找的結(jié)果為空,那么會拋出異常。解決方法時,使用required=false。
將?個類聲明為Spring的 bean 的注解有哪些?
@Component :通?的注解,可標(biāo)注任意類為 Spring 組件。如果?個Bean不知道屬于哪個層,可以使? @Component 注解標(biāo)注。
@Repository : 對應(yīng)持久層即 Dao 層,主要?于數(shù)據(jù)庫相關(guān)操作。
@Service : 對應(yīng)服務(wù)層,主要涉及?些復(fù)雜的邏輯,需要?到 Dao層。
@Controller : 對應(yīng) Spring MVC 控制層,主要?戶接受?戶請求并調(diào)? Service 層返回數(shù)
據(jù)給前端??。
@Component 和 @Bean 的區(qū)別是什么?
作?對象不同: @Component 注解作?于類,? @Bean 注解作?于?法。
@Component 通常是通過類路徑掃描來?動偵測以及?動裝配到Spring容器中(我們可以使? @ComponentScan 注解定義要掃描的路徑從中找出標(biāo)識了需要裝配的類?動裝配到Spring 的 bean 容器中)。
@Bean 注解通常是我們在標(biāo)有該注解的?法中定義產(chǎn)?這個bean, @Bean 告訴了Spring這是某個類的示例,當(dāng)我需要?它的時候還給我。
- @Bean 注解? Component 注解的?定義性更強,?且很多地?我們只能通過 @Bean 注解來注冊bean。?如當(dāng)我們引?第三?庫中的類需要裝配到 Spring 容器時,則只能通過
@Bean 來實現(xiàn)。
@component, @Controller,@Repository,@Service有何區(qū)別?
@Component:這將java類標(biāo)記為bean。它是任何Spring管理組件的通用構(gòu)造型。spring的組件掃描機制現(xiàn)在可以將其拾取并將其拉入應(yīng)用程序環(huán)境中。
@Controller:這將一個類標(biāo)記為Spring Web MVC控制器。標(biāo)有它的Bean 會自動導(dǎo)入到IOC容器中。
@Service:此注解是組件注解的特化。它不會對@Component注解提供任何其他行為。您可以在服務(wù)層類中使用@Service而不是@Component,因為它以更好的方式指定了意圖。
@Repository:這個注解是具有類似用途和功能的@Component注解的特化。它為DAO提供了額外的好處。它將DAO導(dǎo)入IOC容器,并使未經(jīng)檢查的異常有資格轉(zhuǎn)換為Spring DataAccessException。
@Autowired注解有什么作用
@Autowired默認(rèn)是按照類型裝配注入的,默認(rèn)情況下它要求依賴對象必須存在(可以設(shè)置它required屬性為false)。@Autowired 注解提供了更細粒度的控制,包括在何處以及如何完成自動裝配。它的用法和@Required一樣,修飾setter方法、構(gòu)造器、屬性或者具有任意名稱和/或多個參數(shù)的PN方法。
@Autowired和@Resource之間的區(qū)別
@Autowired可用于: 構(gòu)造函數(shù)、成員變量、Setter方法
@Autowired和@Resource之間的區(qū)別
相同點:
1,@Autowired和@Resource功能相同,都可以用來裝配bean;
2,兩個注解可以加載屬性字段或?qū)懺趕etter方法上;
不同點:
1,提供方不同:@Autowired是Spring框架提供,@Resource是Java自帶,jdk1.6版本開始支持;
2,裝配方式不同:
@Autowired默認(rèn)按照byType裝配;
@Resource默認(rèn)按照byName裝配,如果匹配不到,則繼續(xù)使用byType裝配;
@Qualifier注解有什么作用
當(dāng)您創(chuàng)建多個相同類型的bean并希望僅使用屬性裝配其中一個bean時,您可以使用@Qualifier注解和@Autowired通過指定應(yīng)該裝配哪個確切的bean來消除歧義。
@RequestMapping 注解有什么用?
@RequestMapping注解用于將特定HTTP請求方法映射到將處理相應(yīng)請求的控制器中的特定類/方法。此注釋可應(yīng)用于兩個級別:
類級別:注解寫在類上,映射請求的URL
方法級別:注解寫在對應(yīng)的方法上,映射URL以及HTTP請求方法
@RestController vs @Controller
Controller 返回?個??
單獨使? @Controller 不加 @ResponseBody 的話?般使?在要返回?個視圖的情況,這種情況屬于??傳統(tǒng)的Spring MVC 的應(yīng)?,對應(yīng)于前后端不分離的情況。
@RestController 返回JSON 或 XML 形式數(shù)據(jù)
但 @RestController 只返回對象,對象數(shù)據(jù)直接以 JSON 或 XML 形式寫? HTTP 響應(yīng)(Response)中,這種情況屬于 RESTful Web服務(wù),這也是?前?常開發(fā)所接觸的最常?的情況(前后端分離)。
@Controller +@ResponseBody 返回JSON 或 XML 形式數(shù)據(jù)
如果你需要在Spring4之前開發(fā) RESTful Web服務(wù)的話,你需要使? @Controller 并結(jié)合 @ResponseBody 注解,也就是說 @Controller + @ResponseBody = @RestController (Spring 4之后新加的注解)。

解釋下什么是AOP?你的理解是什么?
AOP(Aspect-Oriented Programming:?向切?編程)能夠?qū)⒛切┡c業(yè)務(wù)?關(guān),卻為業(yè)務(wù)模塊所共同調(diào)?的邏輯或責(zé)任(例如事務(wù)處理、?志管理、權(quán)限控制等)封裝起來,便于減少系統(tǒng)的重復(fù)代碼,降低模塊間的耦合度,并有利于未來的可拓展性和可維護性。
Spring AOP就是基于動態(tài)代理的,如果要代理的對象,實現(xiàn)了某個接?,那么Spring AOP會使?JDK Proxy,去創(chuàng)建代理對象,?對于沒有實現(xiàn)接?的對象,就?法使? JDK Proxy 去進?代理了,這時候Spring AOP會使?Cglib ,這時候Spring AOP會使? Cglib ?成?個被代理對象的?類來作為代理,使? AOP 之后我們可以把?些通?功能抽象出來,在需要?到的地?直接使?即可,這樣??簡化了代碼量。我們需要增加新功能時也?便,這樣也提?了系統(tǒng)擴展性。?志功能、事務(wù)管理等等場景都?到了 AOP 。
JDK動態(tài)代理和CGLIB動態(tài)代理的區(qū)別
Spring AOP中的動態(tài)代理主要有兩種方式,JDK動態(tài)代理和CGLIB動態(tài)代理:
JDK動態(tài)代理只提供接口的代理,不支持類的代理。核心InvocationHandler接口和Proxy類,lnvocationHandler通過invoke()方法反射來調(diào)用目標(biāo)類中的代碼,動態(tài)地將橫切邏輯和業(yè)務(wù)編織在一起;接著,Proxy利用InvocationHandler動態(tài)創(chuàng)建一個符合某一接口的的實例,生成目標(biāo)類的代理對象。
如果代理類沒有實現(xiàn)InvocationHandler接口,那么Spring AOP會選擇使用CGLIB來動態(tài)代理目標(biāo)類。CGLIB (Code Generation Library),是一個代碼生成的類庫,可以在運行時動態(tài)的生成指定類的一個子類對象,并覆蓋其中特定方法并添加增強代碼,從而實現(xiàn)AOP。CGLIB是通過繼承的方式做的動態(tài)代理,因此如果某個類被標(biāo)記為final,那么它是無法使用CGLIB做動態(tài)代理的。
靜態(tài)代理與動態(tài)代理區(qū)別在于生成AOP代理對象的時機不同,相對來說AspectJ的靜態(tài)代理方式具有更好的性能,但是AspectJ需要特定的編譯器進行處理,而Spring AOP則無需特定的編譯器處理。

解釋下SpringAOP里面的幾個名詞
切面(Aspect)
切面是通知和切點的結(jié)合。通知和切點共同定義了切面的全部內(nèi)容。在SpringAOP中,切面可以使用通用類(基于模式的風(fēng)格)或者在普通類中以@AspectJ注解來實現(xiàn)。
連接點(Join point)
指方法,在Spring AOP中,一個連接點總是代表一個方法的執(zhí)行。應(yīng)用可能有數(shù)以千計的時機應(yīng)用通知。這些時機被稱為連接點。連接點是在應(yīng)用執(zhí)行過程中能夠插入切面的一個點。這個點可以是調(diào)用方法時、拋出異常時、甚至修改一個字段時。切面代碼可以利用這些點插入到應(yīng)用的正常流程之中,并添加新的行為。
通知(Advice)
在AOP術(shù)語中,切面的工作被稱為通知。
切入點(Pointcut)
切點的定義會匹配通知所要織入的一個或多個連接點。我們通常使用明確的類和方法名稱,或是利用正則表達式定義所匹配的類和方法名稱來指定這些切點。
引入(lntroduction)
引入允許我們向現(xiàn)有類添加新方法或?qū)傩浴?/p>
目標(biāo)對象(Target Object)
被一個或者多個切面(aspect)所通知(advise)的對象。它通常是一個代理對象。也有人把它叫做被通知(adviced)對象。既然Spring AOP是通過運行時代理實現(xiàn)的,這個對象永遠是一個被代理(proxied)對象。
織入(Weaving)
織入是把切面應(yīng)用到目標(biāo)對象并創(chuàng)建新的代理對象的過程。在目標(biāo)對象的生命周期里有多少個點可以進行織入:
編譯期:切面在目標(biāo)類編譯時被織入。AspectJ的織入編譯器是以這種方式織入切面的。
類加載期:切面在目標(biāo)類加載到VM時被織入。需要特殊的類加載器,它可以在目標(biāo)類被引入應(yīng)用之前增強該目標(biāo)類的字節(jié)碼。AspectJ5的加載時織入就支持以這種方式織入切面。
運行期:切面在應(yīng)用運行的某個時刻被織入。一般情況下,在織入切面時,AOP容器會為目標(biāo)對象動態(tài)地創(chuàng)建一個代理對象。SpringAOP就是以這種方式織入切面。
spring通知有哪些類型?
在AOP術(shù)語中,切面的工作被稱為通知,實際上是程序執(zhí)行時要通過SpringAOP框架觸發(fā)的代碼段。Spring切面可以應(yīng)用5種類型的通知:
前置通知(Before) : 在目標(biāo)方法被調(diào)用之前調(diào)用通知功能;
后置通知(After)∶在目標(biāo)方法完成之后調(diào)用通知,此時不會關(guān)心方法的輸出是什么;
返回通知(After-returning ) : 在目標(biāo)方法成功執(zhí)行之后調(diào)用通知;
異常通知(After-throwing): 在目標(biāo)方法拋出異常后調(diào)用通知;
環(huán)繞通知(Around): 通知包裹了被通知的方法,在被通知的方法調(diào)用之前和調(diào)用之后執(zhí)行自定義的行為。

什么是切面Aspect?
aspect由pointcount和advice組成,切面是通知和切點的結(jié)合。
它既包含了橫切邏輯的定義,也包括了連接點的定義.
Spring AOP就是負(fù)責(zé)實施切面的框架,它將切面所定義的橫切邏輯編織到切面所指定的連接點中.
AOP的工作重心在于如何將增強編織目標(biāo)對象的連接點上,這里包含兩個工作:
如何通過pointcut和advice定位到特定的joinpoint 上
如何在advice中編寫切面代碼.
可以簡單地認(rèn)為,使用@Aspect注解的類就是切面.

Spring支持的事務(wù)管理類型,spring事務(wù)實現(xiàn)方式有哪些?
Spring支持兩種類型的事務(wù)管理:
編程式事務(wù)管理:通過編程的方式管理事務(wù),給你帶來極大的靈活性,但是難維護。
編程式事務(wù)管理通過TransactionTemplate手動管理事務(wù),硬編碼方式(不推薦使用)
聲明式事務(wù)管理:你可以將業(yè)務(wù)代碼和事務(wù)管理分離,你只需用注解和XML配置來管理事務(wù)。(在配置文件中配置,推薦使用)
聲明式事務(wù)管理有三種實現(xiàn)方式:
基于TransactionProxyFactoryBean的方式。
基于AspectJ的XML方式。
基于注解的方式大部分。service類名上或方法上添加@Transactional 注解
你更傾向用那種事務(wù)管理類型?
我會選擇聲明式事務(wù)管理,因為它對應(yīng)用代碼的影響最小,因此更符合一個無侵入的輕量級容器的思想。聲明式事務(wù)管理要優(yōu)于編程式事務(wù)管理,雖然比編程式事務(wù)管理(這種方式允許你通過代碼控制事務(wù))少了一點靈活性。唯一不足地方是,最細粒度只能作用到方法級別,無法做到像編程式事務(wù)那樣可以作用到代碼塊級別。
Spring事務(wù)的實現(xiàn)方式和實現(xiàn)原理
Spring事務(wù)的本質(zhì)其實就是數(shù)據(jù)庫對事務(wù)的支持,沒有數(shù)據(jù)庫的事務(wù)支持,spring是無法提供事務(wù)功能的。真正的數(shù)據(jù)庫層的事務(wù)提交和回滾是通過binlog或者redo log實現(xiàn)的。
說一下Spring的事務(wù)傳播行為
spring事務(wù)的傳播行為說的是,當(dāng)多個事務(wù)同時存在的時候,spring如何處理這些事務(wù)的行為。一共七種傳播行為:
PROPAGATION_REQUIRED(required):如果當(dāng)前沒有事務(wù),就創(chuàng)建一個新事務(wù),如果當(dāng)前存在事務(wù),就加入該事務(wù),該設(shè)置是最常用的設(shè)置。
PROPAGATION_SUPPORTS(supports): 支持當(dāng)前事務(wù),如果當(dāng)前存在事務(wù),就加入該事務(wù),如果當(dāng)前不存在事務(wù),就以非事務(wù)執(zhí)行。
PROPAGATION_MANDATORY(mandatory):支持當(dāng)前事務(wù),如果當(dāng)前存在事務(wù),就加入該事務(wù),如果當(dāng)前不存在事務(wù),就拋出異常。
PROPAGATION_REQUIRES_NEW(required_new):創(chuàng)建新事務(wù),無論當(dāng)前存不存在事務(wù),都創(chuàng)建新事務(wù)。
PROPAGATION_NOT_SUPPORTED(not_supported): 以非事務(wù)方式執(zhí)行操作,如果當(dāng)前存在事務(wù),就把當(dāng)前事務(wù)掛起。
PROPAGATION_NEVER(never):以非事務(wù)方式執(zhí)行,如果當(dāng)前存在事務(wù),則拋出異常。
PROPAGATION_NESTED(nested): 如果當(dāng)前存在事務(wù),則在嵌套事務(wù)內(nèi)執(zhí)行。如果當(dāng)前沒有事務(wù),則按REQUIRED屬性執(zhí)行。
說一下Spring的事務(wù)隔離級別?
spring有五大隔離級別,默認(rèn)值為ISOLATION_DEFAULT(使用數(shù)據(jù)庫的設(shè)置),其他四個隔離級別和數(shù)據(jù)庫的隔離級別一致:
lSOLATION_DEFAULT(default): 用底層數(shù)據(jù)庫的設(shè)置隔離級別,數(shù)據(jù)庫設(shè)置的是什么我就用什么;
ISOLATION_READ_UNCOMMITTED(read_uncommitted): 未提交讀,最低隔離級別、事務(wù)未提交前,就可被其他事務(wù)讀?。〞霈F(xiàn)幻讀、臟讀、不可重復(fù)讀);
ISOLATION_READ_COMMITTED(read_committed): 提交讀,一個事務(wù)提交后才能被其他事務(wù)讀取到(會造成幻讀、不可重復(fù)讀),SQL server的默認(rèn)級別;
ISOLATION_REPEATABLE_READ(repeatable_read): 可重復(fù)讀,保證多次讀取同一個數(shù)據(jù)時,其值都和事務(wù)開始時候的內(nèi)容是一致,禁止讀取到別的事務(wù)未提交的數(shù)據(jù)(會造成幻讀),MySQL的默認(rèn)級別;
ISOLATION_SERIALIZABLE(serializable):序列化,代價最高最可靠的隔離級別,該隔離級別能防止臟讀、不可重復(fù)讀、幻讀。
什么是臟讀、幻讀、不可重復(fù)讀?
臟讀∶表示一個事務(wù)能夠讀取另一個事務(wù)中還未提交的數(shù)據(jù)。比如,某個事務(wù)嘗試插入記錄A,此時該事務(wù)還未提交,然后另一個事務(wù)嘗試讀取到了記錄A。
不可重復(fù)讀︰是指在一個事務(wù)內(nèi),多次讀同一數(shù)據(jù)。
幻讀:指同一個事務(wù)內(nèi)多次查詢返回的結(jié)果集不一樣。比如同一個事務(wù)A第一次查詢時候有n條記錄,但是第二次同等條件下查詢卻有n+1條記錄,這就好像產(chǎn)生了幻覺。發(fā)生幻讀的原因也是另外一個事務(wù)新增或者刪除或者修改了第一個事務(wù)結(jié)果集里面的數(shù)據(jù),同一個記錄的數(shù)據(jù)內(nèi)容被修改了,所有數(shù)據(jù)行的記錄就變多或者變少了。
@Transactional(rollbackFor = Exception.class)注解了解嗎?
Exception分為運?時異常RuntimeException和?運?時異常。事務(wù)管理對于企業(yè)應(yīng)
?來說是?關(guān)重要的,即使出現(xiàn)異常情況,它也可以保證數(shù)據(jù)的?致性。
當(dāng) @Transactional 注解作?于類上時,該類的所有 public ?法將都具有該類型的事務(wù)屬性,同時,我們也可以在?法級別使?該標(biāo)注來覆蓋類級別的定義。如果類或者?法加了這個注解,那么這個類??的?法拋出異常,就會回滾,數(shù)據(jù)庫??的數(shù)據(jù)也會回滾。
在 @Transactional 注解中如果不配置 rollbackFor 屬性,那么事物只會在遇到 RuntimeException 的時候才會回滾,加上 rollbackFor=Exception.class ,可以讓事物在遇到?運?時異常時也回滾。