最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解spring面向切面aop攔截器

 更新時(shí)間:2017年03月17日 08:25:37   作者:涂宗勛  
spring中有很多概念和名詞,比如過(guò)濾器、攔截器、aop等。這篇文章主要介紹了詳解spring面向切面aop攔截器,有興趣的可以了解一下。

spring中有很多概念和名詞,其中有一些名字不同,但是從功能上來(lái)看總感覺(jué)是那么的相似,比如過(guò)濾器、攔截器、aop等。
過(guò)濾器filter、spring mvc攔截器Interceptor 、面向切面編程aop,實(shí)際上都具有一定的攔截作用,都是攔截住某一個(gè)面,然后進(jìn)行一定的處理。

在這里主要想著手的是aop,至于他們的比較,我想等三個(gè)都一一了解完了再說(shuō),因此這里便不做過(guò)多的比較。

在我目前的項(xiàng)目實(shí)踐中,只在一個(gè)地方手動(dòng)顯示的使用了aop,那便是日志管理中對(duì)部分重要操作的記錄。

據(jù)我目前所知,aop攔截一般都是用在具體的方法上,或者說(shuō)是具體的某一類(lèi)方法,我所用過(guò)的實(shí)現(xiàn)方式有兩種,一種是直接代碼聲明,一種是在xml文件中配置。

由于我目前實(shí)際開(kāi)發(fā)的項(xiàng)目都是使用spring+spring mvc的架構(gòu),然后使用maven管理,然后junit測(cè)試。因此我自己幾乎所有的個(gè)人項(xiàng)目也都是采用這些架構(gòu)和項(xiàng)目管理工具,在這個(gè)理解aop的小項(xiàng)目中,自然也是這樣,依賴(lài)包如下:

<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>springTest</groupId>
 <artifactId>aopTest</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <dependencies>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.0.3.RELEASE</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>4.0.3.RELEASE</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>4.0.3.RELEASE</version>
  </dependency>
  <dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.8.4</version>
  </dependency>
 </dependencies>
</project>

第一種方式,Java代碼聲明:

這里實(shí)例中,我要聲明一個(gè)aop來(lái)攔截dao層中的get開(kāi)頭的所有方法,首先建一個(gè)dao以及簡(jiǎn)單的額imp實(shí)現(xiàn):

dao接口如下:

package com.ck.aopTest.dao;
import com.ck.aopTest.model.UserModel;

public interface MyAopDao {
  public void getUser();
  public void getName(UserModel user);
  public void addUser();
}

簡(jiǎn)單的實(shí)現(xiàn):

package com.ck.aopTest.dao.impl;
import org.springframework.stereotype.Repository;
import com.ck.aopTest.dao.MyAopDao;
import com.ck.aopTest.model.UserModel;

@Repository
public class MyAopDaoImpl implements MyAopDao {

  @Override
  public void getUser() {
    System.out.println("這是我的aop測(cè)試dao方法一");
  }
  @Override
  public void getName(UserModel userModel) {
    System.out.println("這是我的aop測(cè)試dao方法二");
  }
  @Override
  public void addUser() {
    System.out.println("這是我的aop測(cè)試dao方法三");
  }
}

然后聲明一個(gè)aop:

package com.ck.aopTest.aop;
import java.util.Date;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import com.ck.aopTest.model.UserModel;

@Aspect
@Component
public class MyAop {

  @Pointcut("execution(public * com.ck.aopTest.dao.impl.*.get*(..))")
  private void aopTest() {

  }
  @Before("aopTest()")
  public void before() {
    System.out.println("調(diào)用dao方法前攔截" + new Date().getTime());
  }
  @After("aopTest()" + "&&args(user)")
  public void after(UserModel user) {
    System.out.println(user.getName());
    System.out.println("調(diào)用dao方法之后攔截" + new Date().getTime());
  }
  @Around("aopTest()")
  public void around(ProceedingJoinPoint pdj) {
    System.out.println("調(diào)用dao之前的環(huán)繞攔截" + new Date().getTime());
    try {
      pdj.proceed();
    } catch (Throwable e) {
      e.printStackTrace();
    }
    System.out.println("調(diào)用dao之后的環(huán)繞攔截" + new Date().getTime());
  }
}

上述代碼便是用java聲明aop的核心代碼,其中注解@Aspect的作用的就是告訴spring這是一個(gè)aop類(lèi),然后@Component就不用多說(shuō)了,告訴spring這是一個(gè)需要掃描的類(lèi)。

再往下,@Pointcut(“execution(public * com.ck.aopTest.dao.impl..get(..))”)正式聲明需要攔截的切面,@Pointcut以及后邊的額execution是固定的寫(xiě)法,execution后括號(hào)內(nèi)的內(nèi)容便是具體的切面,這里的意思是攔截所有public的任何返回值或者void的、命名空間是com.ck.aopTest.dao.impl下邊的所有的類(lèi)中的所有g(shù)et開(kāi)頭的擁有任意多個(gè)參數(shù)的方法。

簡(jiǎn)單點(diǎn)說(shuō)也就是當(dāng)任何調(diào)用了com.ck.aopTest.dao.impl這個(gè)包中任何類(lèi)中的get開(kāi)頭的方法,便會(huì)激活這個(gè)aop。

而緊接著上邊這一段,我們看到了一個(gè)private void aopTest() 空的方法,實(shí)際上這個(gè)方法的作用是為這個(gè)aop切面聲明一個(gè)名字,便于使用,也便于在多個(gè)aop切面時(shí)正常區(qū)分。

再后邊的@Before、@After、@Around便是三個(gè)可選攔截方式,見(jiàn)名之意,分別是在上邊聲明的切面指明的方法調(diào)用之前執(zhí)行、調(diào)用之后執(zhí)行、以及環(huán)繞執(zhí)行,調(diào)用之前和調(diào)用之后比較好理解,環(huán)繞的意思是在調(diào)用之前和之后都執(zhí)行一定的邏輯。
從代碼中可以看出,pdj.proceed();之前和之后各打印了兩行數(shù)據(jù),pdj.proceed();就代表了繼續(xù)執(zhí)行,如果是了解filter的應(yīng)該很容易想到這個(gè)方法實(shí)際上和chain.doFilter很像,可以理解成放行。

在這三個(gè)注解之后需要指定要使用的切面,即@Pointcut聲明的切面,指定名稱(chēng)就行。

從代碼中可以看到有一個(gè)地方后邊加了“&&args(UserModel user)”,意思是指定形參,也就是說(shuō)指定的切面中有效方法的參數(shù),例如上邊dao中的getName方法有一個(gè)UserModel類(lèi)型的參數(shù),這里便可以使用。

主要代碼寫(xiě)好了,接下來(lái)還有個(gè)必不可少的步驟,既然是spring項(xiàng)目,是spring的aop,那么自然需要配置spring文件,指明需要spring管理的包:

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:context="http://www.springframework.org/schema/context" " 
  xsi:schemaLocation="http://www.springframework.org/schema/beans 
  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
  http://www.springframework.org/schema/context 
  http://www.springframework.org/schema/context/spring-context-3.0.xsd"> 
  <context:component-scan base-package="com.ck.aopTest.*" />
</beans>

為了驗(yàn)證這里的aop是否真的有效,我寫(xiě)了一個(gè)junit測(cè)試:

package com.ck.aopTest.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.ck.aopTest.dao.MyAopDao;
import com.ck.aopTest.model.UserModel;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring.xml")
public class AopTest {
  @Autowired
  private MyAopDao myAopDao;

  @Test
  public void aopTest2() {
    UserModel user = new UserModel();
    myAopDao.getName(user);
  }
}

按理說(shuō),這里運(yùn)行測(cè)試方法后應(yīng)該打印出很多條輸出,但是遺憾的是結(jié)果只是打印出了dao中的一條輸出,原因是spring配置中并沒(méi)有啟用aop,正確的配置應(yīng)該是下邊這樣:

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:context="http://www.springframework.org/schema/context" 
  xmlns:aop="http://www.springframework.org/schema/aop" 
  xsi:schemaLocation="http://www.springframework.org/schema/beans 
  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
  http://www.springframework.org/schema/context 
  http://www.springframework.org/schema/context/spring-context-3.0.xsd
  http://www.springframework.org/schema/aop
  http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"> 

  <aop:aspectj-autoproxy />
  <context:component-scan base-package="com.ck.aopTest.*" />  

</beans>

我們需要再文件頭加入

xmlns:aop=”http://www.springframework.org/schema/aop”

以及http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
除此之外,還要啟用aop:

<aop:aspectj-autoproxy />

再次運(yùn)行測(cè)試方法會(huì)看到控制臺(tái)如下:

由此證明這個(gè)aop是有效的。

第二種方式,配置文件配置:

同樣的,這里還是用之前的dao以及對(duì)應(yīng)的impl,因此這段代碼便不再重復(fù),不一樣的是具體的aop類(lèi)如下:

package com.ck.aopTest.aop;
public class MyAop2 {
  public void before2() {
    System.out.println("這是我的使用注解的aop,調(diào)用dao之前攔截");
  }
}

可以看到這個(gè)類(lèi)實(shí)際上也是極致簡(jiǎn)單,普通類(lèi),普通方法,沒(méi)有任何特別,然后我們要做的是在spring中配置:

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:context="http://www.springframework.org/schema/context" 
  xmlns:aop="http://www.springframework.org/schema/aop" 
  xsi:schemaLocation="http://www.springframework.org/schema/beans 
  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
  http://www.springframework.org/schema/context 
  http://www.springframework.org/schema/context/spring-context-3.0.xsd
  http://www.springframework.org/schema/aop
  http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"> 

  <aop:aspectj-autoproxy />
  <bean id="myAop2" class="com.ck.aopTest.aop.MyAop2"></bean>
  <aop:config>
   <aop:pointcut expression="execution(public * com.ck.aopTest.dao.impl.*.add*(..))" id="aopTest1"/>
   <aop:aspect id="myAopTest2" ref="myAop2">
    <aop:before method="before2" pointcut-ref="aopTest1"/>
   </aop:aspect>
  </aop:config>
  <context:component-scan base-package="com.ck.aopTest.*" />

</beans>

至于這里配置內(nèi)容的具體解釋?zhuān)蚁胪ㄟ^(guò)我對(duì)第一種方式的解釋后,也沒(méi)有太大必要再說(shuō),稍微一對(duì)比就會(huì)一清二楚。

同樣的,這里只演示了before,至于after和round的配置應(yīng)該也很容易就可以根據(jù)before推理出來(lái)。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論

墨脱县| 兴海县| 牙克石市| 高清| 久治县| 兰溪市| 西乡县| 江安县| 廊坊市| 枣阳市| 江阴市| 航空| 涿鹿县| 当涂县| 临清市| 黄石市| 上思县| 镇远县| 尼木县| 湘阴县| 抚顺市| 临清市| 都昌县| 金山区| 邯郸县| 维西| 通道| 深泽县| 昆明市| 黄陵县| 得荣县| 尉氏县| 陈巴尔虎旗| 简阳市| 呼伦贝尔市| 偃师市| 周宁县| 凉山| 崇阳县| 民勤县| 菏泽市|