上篇博客咱們系統的聊了《JavaEE開發之基於Eclipse的環境搭建以及Maven Web App的建立》,並在以前的博客中咱們聊了依賴注入的相關東西,而且使用Objective-C的Runtime來實現了ObjC中的依賴注入,相關博客請參考《類比Spring框架來實現OC中的依賴注入》。固然以前的博客也是使用了ObjC的Runtime的東西來實現了ObjC中的「面向切面」編程的實現方式,相關博客請移步於《ObjC中的AOP--面向切面編程》。本篇博客咱們就來看一下Spring框架中的依賴注入以及AOP編程的幾種方式,固然其實現方式是使用了Java的「反射機制」,也就相似於ObjC中的Runtime了。html
今天博客中所使用的Spring版本是4.3.6.RELEASE,是目前比較新的Spring版本了。而Java的版本使用的是Java8了。上篇博客咱們主要聊了相關環境的建立與配置,本篇博客將不會對環境配置這些東西進行詳細的敘述。本篇博客主要聊了Spring框架中的依賴注入的實現方式,主要是經過註解以及Java配置來實現的,固然還會聊些AOP的東西。java
1、快速建立Mava管理的Spring工程git
由於本篇博客是討論關於Spring的東西,因此咱們就不建立WebApp的工程了。咱們使用Spring來快速的建立一個Maven管理的工程。以下所示找到File->New->Maven Project選項來建立一個新的Maven Project,具體以下所示:github
下方咱們選擇建立一個簡單的Maven工程,跳過模板的選擇。上篇博客咱們在建立Maven工程時,是沒有選擇下方這個選項的,而後咱們選擇了一個WebApp的模板。而本篇博客,咱們不須要WebApp的模板,只須要一個簡單的Maven工程便可。spring
接着輸入組織名和工程名,以下所示。點擊Finish便可完成Maven簡單工程的建立。apache
下面就是咱們建立好的Maven 工程的目錄結構,咱們的工程代碼要放在src/main/java中,稍後會使用到。編程
建立好上述工程後,咱們要在pom.xml中引入咱們的Spring依賴包。下方xml就是pom.xml中的內容。咱們先引入了spring-context包,以下所示:框架
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.zeluli</groupId> <artifactId>SpringDemoWithMaven</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <java.version>1.8</java.version> <spring.version>4.3.6.RELEASE</spring.version> </properties> <dependencies> <!-- Spring 核心包的引入 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-complier-plugin</artifactId> <version>3.3.9</version> <configuration> <source>${java.version}</source> <target>${java.version}</target> </configuration> </plugin> </plugins> </build> </project>
2、Spring中的依賴注入maven
接下來咱們要來看一下Spring中的依賴注入的調用方式,該部分主要聊了兩種Spring中的依賴注入的方式。一種是註解方式,這種方式也是經常使用的,另外一種就是Java配置類的方式。固然在早期Spring版本中是使用xml進行依賴注入的,由於xml配置的繁瑣以及不方便管理的一些特色,因此咱們在工程中通常使用註解以及Java配置的形式。下方會給出註解以及Java配置的形式,並給出其使用場景。函數
一、使用註解實現依賴注入
本小部分,咱們將使用註解來聲明Spring中的Bean。主要是使用@Service註解來聲明業務邏輯層(Service層)所使用的Bean,使用@Repository註解聲明數據訪問層(DAO層)使用的Bean,使用@Controller註解來聲明展示層的Bean,使用@Component來註解組件的Bean。固然這幾個註解其在底層的實現是大同小異的,其功能也是相似的,只是名稱不一樣。
咱們可使用Spring提供的@Autowired來聲明依賴注入的注入點,也可使用JSR-330提供的@Inject或者JSR-250提供的@Resource註解聲明注入點。下面就來看一下這些註解的使用方式。
(1) @Repository
下方代碼片斷就是使用@Repository註解來聲明的Bean,在數據訪問層會使用該註解來聲明DAO層的Bean。稍後咱們會使用到下方的RepositoryBean。
(2) @Service
下方是咱們使用@Service來聲明的Bean,在業務邏輯層,咱們會使用到@Service註解進行Bean的聲明。在下方代碼段中,咱們使用@Service聲明ServiceBean後,在該類中,咱們注入了RepositoryBean的對象。固然使用的是@Autowired來註解的依賴對象的注入點。也就是說,在運行時,會動態的給下方的repositoryBean分配一個RepositoryBean的對象。以下所示:
(3) @Component
@Component是用來聲明組件的,也就是說你封裝了一個組件,這個組件就是使用@Component來進行註解,使其能夠被注入。下方就是使用了@Component註解聲明的組件。稍後咱們會在Controller中進行調用。
(4) @Controller
接下來咱們就使用@Controller來聲明咱們的控制器,下方的ControllerBean就是咱們的控制器類,固然此處咱們使用@Controller進行的註解。而後在該控制器類中,咱們使用了@Autowired註解來注入ServiceBean和ComponentBean的對象,而後在下方相應的方法中進行了使用。
(5)、建立Spring的配置文件
接下來咱們將建立Spring的配置文件,由於Spring能夠經過此配置文件讀取一些上下文的信息。固然,Spring的配置文件其實就是一個Java類,而後咱們使用@Configuration進行修飾便可。而@ComponentScan("包名")負責指定組件所在的包,也就是說設置完該項後,Spring會自動掃描該包下的@Component、@Service、@Repository、@Controller這些註解。
(6)、建立Main函數進行測試
上面一些列的Bean已經建立完畢,接下來,咱們要建立咱們測試用的Main函數了。首先咱們使用註解配置上下文AnnotationConfigApplicationContext對象來從Java的配置文件中獲取Spring的上下文。而後獲取Controller Bean,下方是調用Controller Bean的相應的方法。最後再將調用的資源關閉掉便可。
(7)、運行結果
上述實現完Main方法後,接下來咱們就能夠對其運行並看起運行效果了。具體運行結果以下所示:
二、Java配置
上面一部分是使用Spring中提供的相關注解來聲明的各類類型的Bean。接下來咱們就在Spring的配置文件來聲明相關的Bean,固然在Java配置文件中聲明的Bean通常是全局的,也就是說一些Bean要定義成全局的對象的話,咱們就在Java配置中來進行Bean的聲明。例如一些公共的組件的Bean,咱們就能夠將其放入到Java的配置文件中。接下來咱們就來看一下Spring配置文件中是如何來聲明Bean的。
(1)、建立Java配置使用的類
首先咱們來建立一個類,此處咱們命名爲JavaConfigBean。而後咱們要在Spring的配置文件中將其聲明爲Bean。咱們能夠看出,下方類就是一個普通的Java類,該類中並無使用任何的註解進行修飾。
(2)、在Spring配置文件中聲明Bean
接下來咱們將會在Spring的配置文件中使用@Bean註解將上述的JavaConfigBean聲明爲Bean對象。下方代碼段就是Spring配置文件中的內容,其中的createJavaConfigBean()方法負責生成上述類的對象。其中咱們使用@Bean註解聲明該方法,該方法會返回JavaConfigBean類的對象。在使用JavaConfigBean的對象時,會將下方生成的對象注入到相應的點上。
(3)、建立依賴JavaConfigBean的Controller
接下來咱們就來建立一個Controller類,在該類中咱們來使用JavaConfigBean的對象。下方就是咱們建立的ControllerBean的類中的具體內容,其中使用了@Autowired註解來聲明的注入點,以下所示:
(4)、建立Main函數以及測試結果
接下來咱們就該建立一個Main函數來進行測試了。在Main函數中依然是調用了ControllerBean的相關方法,以下所示:
3、面向切面編程--(Aspect Oriented Programming)
在前段時間發佈的博客中,咱們已經使用了ObjC的Runtime來演示了AOP編程的實現原理。在Java中利用了Java的「反射機制」來實現的。其實在運行時,咱們經過方法體的交換就能夠實現AOP編程。Spring中的AOP編程也不例外,也是經過方法交換來實現的,本篇博客,咱們就來看一下Spring框架中是如何使用AOP編程的。本部分給出了Spring框架中兩種AOP編程的調用方案,一種是基於註解式的攔截方式,另外一種是基於方法式的攔截。
下方將會分別給出這兩種AOP編程實現的兩種方式。在基於註解式的攔截方式中,咱們須要爲切點方法添加註解,而方法式攔截則不須要在切點方法上作任何操做。
一、引入Spring的AOP依賴包和AspectJ依賴包
下方的XML內容就是咱們要在pom.xml添加的相關依賴配置,下方咱們添加了spring-aop以及aspectj的依賴。aspectj也是一個Java的面向切面編程的依賴包。咱們要作的東西也依賴於aspectj。具體的依賴包的引入以下所示:
<!-- spring aop支持 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>4.3.6.RELEASE</version> </dependency> <!-- aspectj支持 --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.8.9</version> </dependency>
二、基於註解的AOP
接下來咱們將實現基於註解式的AOP實現,下方咱們將建立AOP使用的註解,切面類、被切面的Controller、Spring配置文件以及測試用的Main函數。下方是基於註解的AOP的具體實現。
(1)、建立AOP使用的註解
首先咱們先建立一個註解,該註解會在切入點中進行使用。選擇咱們相應的package,而後右鍵單擊->New->Annotation來建立一個註解。
該註解中的內容比較簡單,具體內容以下所示:
package com.zeluli.aop.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Action { }
(2)、建立切面切入的Controller
接下來咱們就來建立一個切面切入的Controller,此處咱們將該類命名爲AnnotationController。在該Controller中相應方法上,咱們使用上述咱們建立的@Action註解來進行聲明,將其聲明爲咱們切面的切入點。具體以下所示:
(3)、編寫切面類
定義好聲明切點的註解@Action以及被切入的Controller後,接下來,咱們就該建立切面類了。下方建立的LogAspect類就是用來切入AnnotationController類的切面類。具體內容以下所示。
咱們使用@Aspect註解將LogAspect類聲明爲切面,而後使用@Component註解將其聲明爲組件。之因此將其聲明爲組件,是由於咱們能夠將該切面切入到好多類中。而後咱們使用@Pointcut註解來指定切入點,@Pointcut參數就是咱們上面建立的註解@Action。也就是說使用@Action修飾的方法就是咱們的切入點。使用@Before註解來聲明在切點以前執行的方法,使用@After註解來聲明在切點以後執行的方法。下方就是LogAspect類的具體內容。
(4)、建立Spring的配置文件
接着咱們要建立配置類,在配置類中咱們要開啓AspectJ的自動代理,以下所示。
(5)、建立Main函數進行測試
接下來,咱們就開始測試了。Main方法比較簡單,與上面的Main方法大同小異。主要是調用AnnotationConfigApplicationContext來從配置文件中加載上下文,而後根據上下文獲取AnnotationController的對象,而後調用testMethod()方法,最後將上下文進行關閉便可。
public class Main { public static void main(String[] args) { AnnotationConfigApplicationContext aopContext = new AnnotationConfigApplicationContext(AopConfig.class); AnnotationController controller = aopContext.getBean(AnnotationController.class); controller.testMethod(); aopContext.close(); } }
下方截圖就是上述Main方法的運行結果,可見,在testMethod()方法調用以前會執行切片的@Before方法,testMethod()方法執行以後會執行@After方法。具體結果以下所示:
三、基於方法的AOP
上面咱們聊了基於註解攔截的切面,接下來咱們就來看一下基於方法的切面。也就是說在該部分,咱們不會建立註解。直接建立LogAspect切面便可。下方這個LogAspect切面就是基於方法的切面。其中在@Before或者@After註解後邊跟着一串字符串,該字符串就是切入點所在類。以下所示。
上述切面的運行效果與註解切面的運行效果一致,在此就不作過多贅述了。
本篇博客就先到此,上述相關代碼在github上的分享地址爲:https://github.com/lizelu/SpringDemo