Q:依賴倒置原則(Dependency Inversion Principle爱只,DIP),依賴注入(Dependency Injection,DI)和控制反轉(zhuǎn)(Inversion of Control炕置,IoC)容器
依賴倒置原則(Dependency Inversion Principle, DIP)兆沙。這個設(shè)計準則某種程度上和依賴注入模式有些關(guān)聯(lián)欧芽。DIP的出發(fā)點是:在應(yīng)用開發(fā)中,高層模塊不應(yīng)當直接依賴低層模塊葛圃。DIP并不意味著依賴注入千扔。這個準則并沒有講到高層模塊如何知道調(diào)用哪個低層模塊。不過這一點通過實現(xiàn)工廠模式接口可以間接獲知库正,或者通過類似Spring框架曲楚、Pico容器、Guice或者Apache HiveMind之類的loC容器實現(xiàn)依賴注入從而得知高層模塊調(diào)用的具體哪個低層模塊褥符。
依賴注入模式(Dependency Injection):在運行時將類的依賴注入到代碼中龙誊。通過將依賴定義為接口,并將實現(xiàn)這個接口的實體類注入到主類的構(gòu)造器中來實現(xiàn)這個模式喷楣。這允許程序員在不同的實現(xiàn)之間轉(zhuǎn)換而不用去修改主類趟大。依賴注入模式可以通過單一責(zé)任原則(Single Responsibility Principle)SRP來使得代碼高內(nèi)聚(high cohesion),因為所依賴的通常都是完成獨立的功能的對象铣焊,例如逊朽,(通過DAO進行)數(shù)據(jù)存取或(通過Service和Delegate類實現(xiàn))業(yè)務(wù)服務(wù)。
控制反轉(zhuǎn)容器(Inversion of Control Container曲伊,IoC)叽讳,是一個支持依賴注入的容器。這種方式下,可以采用一個中心容器绽榛,例如Spring框架湿酸,Guice或者HiveMind,來定義哪個依賴應(yīng)該使用哪個實體類灭美。Ioc的松耦合性可以帶來更多的靈活性推溃,并且在程序運行時更容易去切換到正確的依賴對象上。控制反轉(zhuǎn)模式的基本概念是届腐,不去實際生成對象铁坎,而是去定義如何生成對象。不用直接在代碼中將模塊和服務(wù)硬編碼在一起犁苏,而是在配置文件中描述哪個模塊需要哪個服務(wù)硬萍。容器(例如Spring框架這個IoC容器)會負責(zé)將這兩者綁定起來。應(yīng)用IoC的時候围详,某對象所需的依賴會在創(chuàng)建的時候通過外部實體傳入朴乖,這些外部實體用來協(xié)調(diào)系統(tǒng)中的不同對象。也就是說助赞,依賴是被注入到對象中去的买羞。因此,IoC就是關(guān)于一個對象如何獲得其協(xié)作對象的引用的一種責(zé)任反轉(zhuǎn)機制雹食。
DI和IoC的真正強大之處在于:
- 在運行時而非編譯時綁定類間關(guān)系畜普。例如,在Seam框架中群叶,你可以對一個接口進行兩種實現(xiàn):真正的實現(xiàn)和模擬(mock)的實現(xiàn)吃挑,而在運行時根據(jù)某個屬性、另一個文件存在與否或者某個優(yōu)先值去決定真正調(diào)用哪一個實現(xiàn)街立。這尤其當你希望程序在不同場景下表現(xiàn)不同的行為時舶衬,這是非常好用的。
- 使得代碼更容易進行單元測試几晤。
- 不用使用工廠或者單例模式就可以實現(xiàn)松耦合约炎,其實現(xiàn)方法一致因此適合缺乏經(jīng)驗的程序員。
Q:IoC中支持的依賴注入有哪些類型蟹瘾?
- 構(gòu)造子注入(例如圾浅,Spring框架):依賴是通過構(gòu)造器參數(shù)提供的。
- 設(shè)值方法注入(例如憾朴,Spring框架):依賴是通過JavaBeans屬性注入的(ex:setter方法)
- 接口注入(例如狸捕,Avalon):注入通過接口完成。
選擇哪種注入方式众雷?
兩種依賴方式都可以使用灸拍,構(gòu)造器注入和Setter方法注入做祝。最好的解決方案是用構(gòu)造器參數(shù)實現(xiàn)強制依賴,setter方法實現(xiàn)可選依賴鸡岗。
Q:Bean的生命周期
BeanFactory中的Bean生命周期
- 在調(diào)用getBean方法之前混槐,如果容器注冊了InstantiationAwareBeanPostProcessor接口,則在實例化bean之前調(diào)用postProcessBeforeInstantiation方法
- 根據(jù)配置情況調(diào)用Bean的構(gòu)造函數(shù)或者工廠方法實例化bean
- 如果容器注冊了InstantiationAwareBeanPostProcessor接口轩性,則在實例化bean之前調(diào)用postProcessAfterInstantiation方法声登,對實例化后的bean進行裝飾
- 如果Bean配置了屬性值,則在配置屬性值之前調(diào)用InstantiationAwareBeanPostProcessor接口的postProcessPropertyValues方法
- 調(diào)用Bean的屬性配置方法設(shè)置屬性值
- 如果Bean實現(xiàn)了BeanNameAware接口揣苏,則調(diào)用setBeanName方法悯嗓,將配置文件中該Bean對應(yīng)的名稱設(shè)置到Bean中
- 如果Bean實現(xiàn)了BeanFactoryAware接口,則調(diào)用setBeanFactory方法卸察,將BeanFactory實例傳到Bean中
- 如果容器注冊了BeanPostProcessor接口脯厨,則調(diào)用postProcessBeforeInitialzation(Object bean,String beanName)方法對Bean進行加工操作坑质,返回對象為加工后的Bean合武。BeanPostProcessor在Spring框架占有有重要地位,Spring提供的AOP以及動態(tài)代理均通過此接口完成洪乍。
- 如果Bean實現(xiàn)了InitializingBean接口眯杏,那么調(diào)用afterPropertiesSet方法
- 如果<bean>中通過init-method定義了初始化方法,則執(zhí)行此方法
- 如果容器注冊了BeanPostProcessor接口壳澳,則調(diào)用postProcessAfterInitialzation(Object bean,String beanName)方法茫经,再次提供對Bean的加工機會
- 如果在<bean>中指定Bean的作用范圍為scope="prototype"巷波,將Bean返回給調(diào)用者,調(diào)用者負責(zé)Bean后續(xù)生命管理卸伞。如果scope="singleton"抹镊,則將Bean放入Spring IoC容器的緩存池中,并將Bean引用返回給調(diào)用者荤傲,Spring繼續(xù)對Bean的后續(xù)生命周期進行管理
- 對于scope="prototype"的Bean垮耳,當容器關(guān)閉時,將觸發(fā)Spring對Bean的后續(xù)生命管理工作遂黍,如果Bean實現(xiàn)了DisposableBean接口终佛,則將調(diào)用afterPropertiesSet方法,可再次編寫釋放資源雾家,記錄日志等操作
- 對于scope="prototype"的Bean铃彰,如果<bean>中通過destroy-method定義了銷毀方法,則執(zhí)行此方法
Bean的完整生命周期經(jīng)歷了各種方法調(diào)用芯咧,這些方法可以劃分為以下幾類:
- Bean自身的方法
這個包括了Bean本身調(diào)用的方法和通過配置文件中<bean>的init-method和destroy-method指定的方法 - Bean級生命周期接口方法
這個包括了BeanNameAware牙捉、BeanFactoryAware竹揍、InitializingBean和DiposableBean這些接口的方法 - 容器級生命周期接口方法
這個包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 這兩個接口實現(xiàn),一般稱它們的實現(xiàn)類為“后處理器”邪铲。
Q:Bean的作用域
- singleton:這種bean范圍是默認的芬位,這種范圍確保不管接受到多少個請求,每個容器中只有一個bean的實例带到,單例的模式由bean factory自身來維護晶衷。
- prototype:原形范圍與單例范圍相反,為每一個bean請求提供一個實例阴孟。
- request:在請求bean范圍內(nèi)會每一個來自客戶端的網(wǎng)絡(luò)請求創(chuàng)建一個實例晌纫,在請求完成以后,bean會失效并被垃圾回收器回收永丝。
- Session:與請求范圍類似锹漱,確保每個session中有一個bean的實例,在session過期后慕嚷,bean會隨之失效哥牍。
- global-session:global-session和Portlet應(yīng)用相關(guān)。當你的應(yīng)用部署在Portlet容器中工作時喝检,它包含很多portlet嗅辣。如果你想要聲明讓所有的portlet共用全局的存儲變量的話,那么這全局變量需要存儲在global-session中挠说。
Q:BeanFactory和ApplicationContext區(qū)別
ApplicationContext 的主要實現(xiàn)類是ClassPathXmlApplicationContext 和FileSystemXmlApplicationContext澡谭,前者默認從類路徑加載配置文件,后者默認從文件系統(tǒng)中裝載配置文件损俭。
- 利用MessageSource進行國際化
- 事件發(fā)布機制
讓容器擁有發(fā)布應(yīng)用上下文事件的功能蛙奖,包括容器啟動事件、關(guān)閉事件等杆兵。實現(xiàn)了 ApplicationListener 事件監(jiān)聽接口的Bean 可以接收到容器事件雁仲, 并對事件進行響應(yīng)處理。在ApplicationContext 抽象實現(xiàn)類AbstractApplicationContext 中琐脏,我們可以發(fā)現(xiàn)存在一個ApplicationEventMulticaster攒砖,它負責(zé)保存所有監(jiān)聽器,以便在容器產(chǎn)生上下文事件時通知這些事件監(jiān)聽 者日裙。 - 底層資源的訪問
ApplicationContext擴展了ResourceLoader(資源加載器)接口吹艇,從而可以用來加載多個Resource,而BeanFactory是沒有擴展ResourceLoader - LifeCircle
該接口提供start()和stop()方法用于控制異步訪問阅签。在具體使用時該接口同時被ApplicationContext以及Bean實現(xiàn)掐暮,ApplicationContext會將start/stop中的信息傳遞給容器中實現(xiàn)了該接口的Bean - BeanFactroy采用的是延遲加載形式來注入Bean的,即只有在使用到某個Bean時(調(diào)用getBean())政钟,才對該Bean進行加載實例化路克,這樣樟结,我們就不能發(fā)現(xiàn)一些存在的Spring的配置問題。而ApplicationContext則相反精算,它是在容器啟動時瓢宦,一次性創(chuàng)建了所有的Bean。這樣灰羽,在容器啟動時驮履,我們就可以發(fā)現(xiàn)Spring中存在的配置錯誤。
- BeanFactory和ApplicationContext都支持BeanPostProcessor廉嚼、BeanFactoryPostProcessor以及InstantiationAwareBeanPostProcessor 的使用玫镐,但兩者之間的區(qū)別是:BeanFactory需要手動注冊,而ApplicationContext則是自動注冊
Q:IoC容器內(nèi)部工作機制
Spring中的org.springframework.beans包和org.springframework.context包構(gòu)成了Spring框架IoC容器的基礎(chǔ)怠噪。
BeanFactory 接口提供了一個先進的配置機制恐似,使得任何類型的對象的配置成為可能。ApplicationContex接口對BeanFactory(是一個子接口)進行了擴展傍念,在BeanFactory的基礎(chǔ)上添加了其他功能矫夷,比如與Spring的AOP更容易集成,也提供了處理[]message resource的機制(用于國際化)憋槐、事件傳播以及應(yīng)用層的特別配置双藕,比如針對Web應(yīng)用的WebApplicationContext。
org.springframework.beans.factory.BeanFactory是Spring IoC容器的具體實現(xiàn)阳仔,是Spring IoC 容器的核心接口忧陪,用來包裝和管理前面提到的各種bean。
- ResourceLoader從存儲介質(zhì)中加載Spring配置文件驳概,并使用Resource表示這個配置文件的資源赤嚼;
- BeanDefinitionReader讀取Resource所指向的配置文件資源,然后解析配置文件顺又。配置文件中每一個<bean>解析成一個BeanDefinition對象,并保存到BeanDefinitionRegistry中等孵;
- 容器掃描BeanDefinitionRegistry中的BeanDefinition稚照,使用Java的反射機制自動識別出Bean工廠后處理器(實現(xiàn)BeanFactoryPostProcessor接口)的Bean,然后調(diào)用這些Bean工廠后處理器對BeanDefinitionRegistry中的BeanDefinition進行加工處理俯萌。主要完成以下兩項工作:
(1)對使用到占位符的<bean>元素標簽進行解析果录,得到最終的配置值,這意味對一些半成品式的BeanDefinition對象進行加工處理并得到成品的BeanDefinition對象咐熙;
(2)對BeanDefinitionRegistry中的BeanDefinition進行掃描弱恒,通過Java反射機制找出所有屬性編輯器的Bean(實現(xiàn)java.beans.PropertyEditor接口的Bean),并自動將它們注冊到Spring容器的屬性編輯器注冊表中(PropertyEditorRegistry)棋恼; - Spring容器從BeanDefinitionRegistry中取出加工后的BeanDefinition返弹,并調(diào)用InstantiationStrategy著手進行Bean實例化的工作锈玉;
- 在實例化Bean時,Spring容器使用BeanWrapper對Bean進行封裝义起,BeanWrapper提供了很多以Java反射機制操作Bean的方法拉背,它將結(jié)合該Bean的BeanDefinition以及容器中屬性編輯器,完成Bean屬性的設(shè)置工作默终;
- 利用容器中注冊的Bean后處理器(實現(xiàn)BeanPostProcessor接口的Bean)對已經(jīng)完成屬性設(shè)置工作的Bean進行后續(xù)加工椅棺,直接裝配出一個準備就緒的Bean。
Q:請舉例說明如何在Spring中注入一個Java Collection齐蔽?
Spring提供了以下四種集合類的配置元素:
- <list> : 該標簽用來裝配可重復(fù)的list值
- <set> : 該標簽用來裝配沒有重復(fù)的set值
- <map>: 該標簽可用來注入鍵和值可以為任何類型的鍵值對
- <props> : 該標簽支持注入鍵和值都是字符串類型的鍵值對
<beans>
<!-- Definition for javaCollection -->
<bean id="javaCollection" class="com.howtodoinjava.JavaCollection">
<!-- java.util.List -->
<property name="customList">
<list>
<value>INDIA</value>
<value>Pakistan</value>
<value>USA</value>
<value>UK</value>
</list>
</property>
<!-- java.util.Set -->
<property name="customSet">
<set>
<value>INDIA</value>
<value>Pakistan</value>
<value>USA</value>
<value>UK</value>
</set>
</property>
<!-- java.util.Map -->
<property name="customMap">
<map>
<entry key="1" value="INDIA"/>
<entry key="2" value="Pakistan"/>
<entry key="3" value="USA"/>
<entry key="4" value="UK"/>
</map>
</property>
<!-- java.util.Properties -->
<property name="customProperies">
<props>
<prop key="admin">admin@nospam.com</prop>
<prop key="support">support@nospam.com</prop>
</props>
</property>
</bean>
</beans>
Q:Spring Bean的自動裝配
在Spring框架中两疚,在配置文件中設(shè)定bean的依賴關(guān)系是一個很好的機制,Spring容器還可以自動裝配合作關(guān)系bean之間的關(guān)聯(lián)關(guān)系含滴。這意味著Spring可以通過向Bean Factory中注入的方式自動搞定bean之間的依賴關(guān)系诱渤。自動裝配可以設(shè)置在每個bean上,也可以設(shè)定在特定的bean上蛙吏。
下面的XML配置文件表明了如何根據(jù)名稱將一個bean設(shè)置為自動裝配:
<bean id="employeeDAO" class="com.howtodoinjava.EmployeeDAOImpl" autowire="byName" />
除了bean配置文件中提供的自動裝配模式源哩,還可以使用@Autowired注解來自動裝配指定的bean。在使用@Autowired注解之前需要在按照如下的配置方式在Spring配置文件進行配置才可以使用鸦做。
<context:annotation-config />
也可以通過在配置文件中配置AutowiredAnnotationBeanPostProcessor 達到相同的效果励烦。
<bean class ="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
配置好以后就可以使用@Autowired來標注了。
自動裝配局限性
- 重寫: 你仍需用 <constructor-arg>和 <property> 配置來定義依賴坛掠,意味著總要重寫自動裝配。
- 基本數(shù)據(jù)類型:你不能自動裝配簡單的屬性治筒,如基本數(shù)據(jù)類型屉栓,String字符串,和類耸袜。
- 模糊特性:自動裝配不如顯式裝配精確友多,如果有可能,建議使用顯式裝配堤框。
Q:Spring三種配置方式
1 基于XML配置的方式配置Spring
在Spring框架中域滥,依賴和服務(wù)需要在專門的配置文件來實現(xiàn),我常用的XML格式的配置文件蜈抓。這些配置文件的格式通常用<beans>開頭启绰,然后一系列的bean定義和專門的應(yīng)用配置選項組成。
SpringXML配置的主要目的時候是使所有的Spring組件都可以用xml文件的形式來進行配置沟使。這意味著不會出現(xiàn)其他的Spring配置類型(比如聲明的方式或基于Java Class的配置方式)
Spring的XML配置方式是使用被Spring命名空間的所支持的一系列的XML標簽來實現(xiàn)的委可。Spring有以下主要的命名空間:context、beans腊嗡、jdbc着倾、tx拾酝、aop、mvc和aso屈呕。
<beans>
<!-- JSON Support -->
<bean name="viewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
<bean name="jsonTemplate" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate"/>
</beans>
下面這個web.xml僅僅配置了DispatcherServlet微宝,這件最簡單的配置便能滿足應(yīng)用程序配置運行時組件的需求。
<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>
2 基于Java配置的方式配置Spring
Spring對Java配置的支持是由@Configuration注解和@Bean注解來實現(xiàn)的虎眨。由@Bean注解的方法將會實例化蟋软、配置和初始化一個新對象,這個對象將由Spring的IoC容器來管理嗽桩。@Bean聲明所起到的作用與<bean/> 元素類似岳守。被@Configuration所注解的類則表示這個類的主要目的是作為bean定義的資源。被@Configuration聲明的類可以通過在同一個類的內(nèi)部調(diào)用@bean方法來設(shè)置嵌入bean的依賴關(guān)系碌冶。
最簡單的@Configuration 聲明類請參考下面的代碼:
@Configuration
public class AppConfig
{
@Bean
public MyService myService() {
return new MyServiceImpl();
}
}
對于上面的@Beans配置文件相同的XML配置文件如下:
<beans>
<bean id="myService" class="com.howtodoinjava.services.MyServiceImpl"/>
</beans>
上述配置方式的實例化方式如下:利用AnnotationConfigApplicationContext 類進行實例化
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
MyService myService = ctx.getBean(MyService.class);
myService.doStuff();
}
要使用組件組建掃描湿痢,僅需用@Configuration進行注解即可:
@Configuration
@ComponentScan(basePackages = "com.howtodoinjava")
public class AppConfig {
...
}
在上面的例子中,com.acme包首先會被掃到扑庞,然后再容器內(nèi)查找被@Component 聲明的類譬重,找到后將這些類按照Sring bean定義進行注冊。
如果你要在你的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.howtodoinjava.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.howtodoinjava.web.MvcConfig</param-value>
</init-param>
</servlet>
<!-- map all requests for /app/* to the dispatcher servlet -->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
</web-app>
3 用注解的方式配置Spring
Spring在2.5版本以后開始支持用注解的方式來配置依賴注入栅隐∷遥可以用注解的方式來替代XML方式的bean描述,可以將bean描述轉(zhuǎn)移到組件類的內(nèi)部租悄,只需要在相關(guān)類上谨究、方法上或者字段聲明上使用注解即可。注解注入將會被容器在XML注入之前被處理泣棋,所以后者會覆蓋掉前者對于同一個屬性的處理結(jié)果胶哲。
注解裝配在Spring中是默認關(guān)閉的。所以需要在Spring文件中配置一下才能使用基于注解的裝配模式潭辈。如果你想要在你的應(yīng)用程序中使用關(guān)于注解的方法的話纪吮,請參考如下的配置。
<beans>
<context:annotation-config/>
<!-- bean definitions go here -->
</beans>
在 <context:annotation-config/>標簽配置完成以后萎胰,就可以用注解的方式在Spring中向?qū)傩浴⒎椒ê蜆?gòu)造方法中自動裝配變量棚辽。
下面是幾種比較重要的注解類型:
@Required:該注解應(yīng)用于設(shè)值方法技竟。
@Autowired:該注解應(yīng)用于有值設(shè)值方法、非設(shè)值方法屈藐、構(gòu)造方法和變量榔组。
@Qualifier:該注解和@Autowired注解搭配使用熙尉,用于消除特定bean自動裝配的歧義。
JSR-250 Annotations:Spring支持基于JSR-250 注解的以下注解搓扯,@Resource检痰、@PostConstruct 和 @PreDestroy。
Q:Spring中AOP相關(guān)基礎(chǔ)問題
解釋AOP:
面向切面的編程锨推,或AOP铅歼, 是一種編程技術(shù),允許程序模塊化橫向切割關(guān)注點换可,或橫切典型的責(zé)任劃分椎椰,如日志和事務(wù)管理。Aspect 切面:
AOP核心就是切面沾鳄,它將多個類的通用行為封裝成可重用的模塊慨飘,該模塊含有一組API提供橫切功能。比如译荞,一個日志模塊可以被稱作日志的AOP切面瓤的。根據(jù)需求的不同,一個應(yīng)用程序可以有若干切面吞歼。在Spring AOP中圈膏,切面通過帶有@Aspect注解的類實現(xiàn)。關(guān)注點和橫切關(guān)注的區(qū)別
關(guān)注點是應(yīng)用中一個模塊的行為浆熔,一個關(guān)注點可能會被定義成一個我們想實現(xiàn)的一個功能本辐。
橫切關(guān)注點是一個關(guān)注點,此關(guān)注點是整個應(yīng)用都會使用的功能医增,并影響整個應(yīng)用慎皱,比如日志,安全和數(shù)據(jù)傳輸叶骨,幾乎應(yīng)用的每個模塊都需要的功能茫多。因此這些都屬于橫切關(guān)注點。連接點
連接點代表一個應(yīng)用程序的某個位置忽刽,在這個位置我們可以插入一個AOP切面天揖,它實際上是個應(yīng)用程序執(zhí)行Spring AOP的位置。