篇博客我們系統(tǒng)的聊了《JavaEE開發(fā)之基于Eclipse的環(huán)境搭建以及Maven Web App的創(chuàng)建》,并在之前的博客中我們聊了依賴注入的相關(guān)東西,并且使用Objective-C的Runtime來實(shí)現(xiàn)了ObjC中的依賴注入,相關(guān)博客請參考《類比Spring框架來實(shí)現(xiàn)OC中的依賴注入》。當(dāng)然之前的博客也是使用了ObjC的Runtime的東西來實(shí)現(xiàn)了ObjC中的“面向切面”編程的實(shí)現(xiàn)方式,相關(guān)博客請移步于《ObjC中的AOP--面向切面編程》。本篇博客我們就來看一下Spring框架中的依賴注入以及AOP編程的幾種方式,當(dāng)然其實(shí)現(xiàn)方式是使用了Java的“反射機(jī)制”,也就類似于ObjC中的Runtime了。
今天博客中所使用的Spring版本是4.3.6.RELEASE,是目前比較新的Spring版本了。而Java的版本使用的是Java8了。上篇博客我們主要聊了相關(guān)環(huán)境的創(chuàng)建與配置,本篇博客將不會對環(huán)境配置這些東西進(jìn)行詳細(xì)的敘述。本篇博客主要聊了Spring框架中的依賴注入的實(shí)現(xiàn)方式,主要是通過注解以及Java配置來實(shí)現(xiàn)的,當(dāng)然還會聊些AOP的東西。
一、快速創(chuàng)建Mava管理的Spring工程
因?yàn)楸酒┛褪怯懻撽P(guān)于Spring的東西,所以我們就不創(chuàng)建WebApp的工程了。我們使用Spring來快速的創(chuàng)建一個(gè)Maven管理的工程。如下所示找到File->New->Maven Project選項(xiàng)來創(chuàng)建一個(gè)新的Maven Project,具體如下所示:
下方我們選擇創(chuàng)建一個(gè)簡單的Maven工程,跳過模板的選擇。上篇博客我們在創(chuàng)建Maven工程時(shí),是沒有選擇下方這個(gè)選項(xiàng)的,然后我們選擇了一個(gè)WebApp的模板。而本篇博客,我們不需要WebApp的模板,只需要一個(gè)簡單的Maven工程即可。
接著輸入組織名和工程名,如下所示。點(diǎn)擊Finish即可完成Maven簡單工程的創(chuàng)建。
下面就是我們創(chuàng)建好的Maven 工程的目錄結(jié)構(gòu),我們的工程代碼要放在src/main/java中,稍后會使用到。
創(chuàng)建好上述工程后,我們要在pom.xml中引入我們的Spring依賴包。下方xml就是pom.xml中的內(nèi)容。我們先引入了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>
二、Spring中的依賴注入
接下來我們要來看一下Spring中的依賴注入的調(diào)用方式,該部分主要聊了兩種Spring中的依賴注入的方式。一種是注解方式,這種方式也是常用的,另一種就是Java配置類的方式。當(dāng)然在早期Spring版本中是使用xml進(jìn)行依賴注入的,因?yàn)閤ml配置的繁瑣以及不方便管理的一些特點(diǎn),所以我們在工程中一般使用注解以及Java配置的形式。下方會給出注解以及Java配置的形式,并給出其使用場景。
1、使用注解實(shí)現(xiàn)依賴注入
本小部分,我們將使用注解來聲明Spring中的Bean。主要是使用@Service注解來聲明業(yè)務(wù)邏輯層(Service層)所使用的Bean,使用@Repository注解聲明數(shù)據(jù)訪問層(DAO層)使用的Bean,使用@Controller注解來聲明展現(xiàn)層的Bean,使用@Component來注解組件的Bean。當(dāng)然這幾個(gè)注解其在底層的實(shí)現(xiàn)是大同小異的,其功能也是類似的,只是名稱不同。
我們可以使用Spring提供的@Autowired來聲明依賴注入的注入點(diǎn),也可以使用JSR-330提供的@Inject或者JSR-250提供的@Resource注解聲明注入點(diǎn)。下面就來看一下這些注解的使用方式。
(1) @Repository
下方代碼片段就是使用@Repository注解來聲明的Bean,在數(shù)據(jù)訪問層會使用該注解來聲明DAO層的Bean。稍后我們會使用到下方的RepositoryBean。
(2) @Service
下方是我們使用@Service來聲明的Bean,在業(yè)務(wù)邏輯層,我們會使用到@Service注解進(jìn)行Bean的聲明。在下方代碼段中,我們使用@Service聲明ServiceBean后,在該類中,我們注入了RepositoryBean的對象。當(dāng)然使用的是@Autowired來注解的依賴對象的注入點(diǎn)。也就是說,在運(yùn)行時(shí),會動態(tài)的給下方的repositoryBean分配一個(gè)RepositoryBean的對象。如下所示:
(3) @Component
@Component是用來聲明組件的,也就是說你封裝了一個(gè)組件,這個(gè)組件就是使用@Component來進(jìn)行注解,使其可以被注入。下方就是使用了@Component注解聲明的組件。稍后我們會在Controller中進(jìn)行調(diào)用。
(4) @Controller
接下來我們就使用@Controller來聲明我們的控制器,下方的ControllerBean就是我們的控制器類,當(dāng)然此處我們使用@Controller進(jìn)行的注解。然后在該控制器類中,我們使用了@Autowired注解來注入ServiceBean和ComponentBean的對象,然后在下方相應(yīng)的方法中進(jìn)行了使用。
(5)、創(chuàng)建Spring的配置文件
接下來我們將創(chuàng)建Spring的配置文件,因?yàn)镾pring可以通過此配置文件讀取一些上下文的信息。當(dāng)然,Spring的配置文件其實(shí)就是一個(gè)Java類,然后我們使用@Configuration進(jìn)行修飾即可。而@ComponentScan("包名")負(fù)責(zé)指定組件所在的包,也就是說設(shè)置完該項(xiàng)后,Spring會自動掃描該包下的@Component、@Service、@Repository、@Controller這些注解。
(6)、創(chuàng)建Main函數(shù)進(jìn)行測試
上面一些列的Bean已經(jīng)創(chuàng)建完畢,接下來,我們要創(chuàng)建我們測試用的Main函數(shù)了。首先我們使用注解配置上下文AnnotationConfigApplicationContext對象來從Java的配置文件中獲取Spring的上下文。然后獲取Controller Bean,下方是調(diào)用Controller Bean的相應(yīng)的方法。最后再將調(diào)用的資源關(guān)閉掉即可。
(7)、運(yùn)行結(jié)果
上述實(shí)現(xiàn)完Main方法后,接下來我們就可以對其運(yùn)行并看起運(yùn)行效果了。具體運(yùn)行結(jié)果如下所示:
2、Java配置
上面一部分是使用Spring中提供的相關(guān)注解來聲明的各種類型的Bean。接下來我們就在Spring的配置文件來聲明相關(guān)的Bean,當(dāng)然在Java配置文件中聲明的Bean一般是全局的,也就是說一些Bean要定義成全局的對象的話,我們就在Java配置中來進(jìn)行Bean的聲明。例如一些公共的組件的Bean,我們就可以將其放入到Java的配置文件中。接下來我們就來看一下Spring配置文件中是如何來聲明Bean的。
(1)、創(chuàng)建Java配置使用的類
首先我們來創(chuàng)建一個(gè)類,此處我們命名為JavaConfigBean。然后我們要在Spring的配置文件中將其聲明為Bean。我們可以看出,下方類就是一個(gè)普通的Java類,該類中并沒有使用任何的注解進(jìn)行修飾。
(2)、在Spring配置文件中聲明Bean
接下來我們將會在Spring的配置文件中使用@Bean注解將上述的JavaConfigBean聲明為Bean對象。下方代碼段就是Spring配置文件中的內(nèi)容,其中的createJavaConfigBean()方法負(fù)責(zé)生成上述類的對象。其中我們使用@Bean注解聲明該方法,該方法會返回JavaConfigBean類的對象。在使用JavaConfigBean的對象時(shí),會將下方生成的對象注入到相應(yīng)的點(diǎn)上。
(3)、創(chuàng)建依賴JavaConfigBean的Controller
接下來我們就來創(chuàng)建一個(gè)Controller類,在該類中我們來使用JavaConfigBean的對象。下方就是我們創(chuàng)建的ControllerBean的類中的具體內(nèi)容,其中使用了@Autowired注解來聲明的注入點(diǎn),如下所示:
(4)、創(chuàng)建Main函數(shù)以及測試結(jié)果
接下來我們就該創(chuàng)建一個(gè)Main函數(shù)來進(jìn)行測試了。在Main函數(shù)中依然是調(diào)用了ControllerBean的相關(guān)方法,如下所示:
三、面向切面編程--(Aspect Oriented Programming)
在前段時(shí)間發(fā)布的博客中,我們已經(jīng)使用了ObjC的Runtime來演示了AOP編程的實(shí)現(xiàn)原理。在Java中利用了Java的“反射機(jī)制”來實(shí)現(xiàn)的。其實(shí)在運(yùn)行時(shí),我們通過方法體的交換就可以實(shí)現(xiàn)AOP編程。Spring中的AOP編程也不例外,也是通過方法交換來實(shí)現(xiàn)的,本篇博客,我們就來看一下Spring框架中是如何使用AOP編程的。本部分給出了Spring框架中兩種AOP編程的調(diào)用方案,一種是基于注解式的攔截方式,另一種是基于方法式的攔截。
下方將會分別給出這兩種AOP編程實(shí)現(xiàn)的兩種方式。在基于注解式的攔截方式中,我們需要為切點(diǎn)方法添加注解,而方法式攔截則不需要在切點(diǎn)方法上做任何操作。
1、引入Spring的AOP依賴包和AspectJ依賴包
下方的XML內(nèi)容就是我們要在pom.xml添加的相關(guān)依賴配置,下方我們添加了spring-aop以及aspectj的依賴。aspectj也是一個(gè)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>
2、基于注解的AOP
接下來我們將實(shí)現(xiàn)基于注解式的AOP實(shí)現(xiàn),下方我們將創(chuàng)建AOP使用的注解,切面類、被切面的Controller、Spring配置文件以及測試用的Main函數(shù)。下方是基于注解的AOP的具體實(shí)現(xiàn)。
(1)、創(chuàng)建AOP使用的注解
首先我們先創(chuàng)建一個(gè)注解,該注解會在切入點(diǎn)中進(jìn)行使用。選擇我們相應(yīng)的package,然后右鍵單擊->New->Annotation來創(chuàng)建一個(gè)注解。
該注解中的內(nèi)容比較簡單,具體內(nèi)容如下所示:
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) @Documentedpublic @interface Action { }
(2)、創(chuàng)建切面切入的Controller
接下來我們就來創(chuàng)建一個(gè)切面切入的Controller,此處我們將該類命名為AnnotationController。在該Controller中相應(yīng)方法上,我們使用上述我們創(chuàng)建的@Action注解來進(jìn)行聲明,將其聲明為我們切面的切入點(diǎn)。具體如下所示:
(3)、編寫切面類
定義好聲明切點(diǎn)的注解@Action以及被切入的Controller后,接下來,我們就該創(chuàng)建切面類了。下方創(chuàng)建的LogAspect類就是用來切入AnnotationController類的切面類。具體內(nèi)容如下所示。
我們使用@Aspect注解將LogAspect類聲明為切面,然后使用@Component注解將其聲明為組件。之所以將其聲明為組件,是因?yàn)槲覀兛梢詫⒃撉忻媲腥氲胶枚囝愔?。然后我們使?span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);">@Pointcut注解來指定切入點(diǎn),@Pointcut參數(shù)就是我們上面創(chuàng)建的注解@Action。也就是說使用@Action修飾的方法就是我們的切入點(diǎn)。使用@Before注解來聲明在切點(diǎn)之前執(zhí)行的方法,使用@After注解來聲明在切點(diǎn)之后執(zhí)行的方法。下方就是LogAspect類的具體內(nèi)容。
(4)、創(chuàng)建Spring的配置文件
接著我們要創(chuàng)建配置類,在配置類中我們要開啟AspectJ的自動代理,如下所示。
(5)、創(chuàng)建Main函數(shù)進(jìn)行測試
接下來,我們就開始測試了。Main方法比較簡單,與上面的Main方法大同小異。主要是調(diào)用AnnotationConfigApplicationContext來從配置文件中加載上下文,然后根據(jù)上下文獲取AnnotationController的對象,然后調(diào)用testMethod()方法,最后將上下文進(jìn)行關(guān)閉即可。
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方法的運(yùn)行結(jié)果,可見,在testMethod()方法調(diào)用之前會執(zhí)行切片的@Before方法,testMethod()方法執(zhí)行之后會執(zhí)行@After方法。具體結(jié)果如下所示:
3、基于方法的AOP
上面我們聊了基于注解攔截的切面,接下來我們就來看一下基于方法的切面。也就是說在該部分,我們不會創(chuàng)建注解。直接創(chuàng)建LogAspect切面即可。下方這個(gè)LogAspect切面就是基于方法的切面。其中在@Before或者@After注解后邊跟著一串字符串,該字符串就是切入點(diǎn)所在類。如下所示。
上述切面的運(yùn)行效果與注解切面的運(yùn)行效果一致,在此就不做過多贅述了。
本篇博客就先到此,上述相關(guān)代碼在github上的分享地址為:https://github.com/lizelu/SpringDemo
作者:青玉伏案
出處:http://www.cnblogs.com/ludashi/
本文版權(quán)歸作者和共博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。
如果文中有什么錯(cuò)誤,歡迎指出。以免更多的人被誤導(dǎo)。
http://www.cnblogs.com/ludashi/p/6541925.html