一:目標類 Seller.java
package aopAspectj;
public class Seller {
public void sellerBefore(){
System.out.println("in seller sellerBefore run");
}
public void sellerBeforeParam(String name){
System.out.println("in seller sellerBeforeParma run--->"+name);
}
public void sellerCommonMethod(String name){
System.out.println("in seller commonMethod run--->"+name);
}
public void sellerAfter(){
System.out.println("in seller sellerAfter run");
}
public void sellerAfterThrowing() throws Exception{
System.out.println("in seller sellerAfterThrowing run");
throw new Exception("exception");
}
public String sellerAfterReturn(String name){
System.out.println("in seller sellerReturn run--->"+name);
return name;
}
public void sellerAround(){
System.out.println("in seller sellerAround run");
}
}
二:切面類(增強)
package aopAspectj;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
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.hibernate.annotations.Target;
import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;
/**
* 通過註解定義一個切面。 通過@Aspect註解定義advisor時,沒有繼承任何類和實現任何接口,我們在
* advisor包中配置的兩個切面都實現了接口,只不過regexp切面 本身的
* 功能已經很完善,沒有對齊進行擴展,而StaticMethodMatcherPointcutAdvisor切面我們定義了一個擴展類
*
* 所有的增強方法都可以加入入參 JointPoint 用以獲得鏈接點信息,around增強比較特殊,是ProceedingJoinPoint
* @author majian
*
*/
@Aspect
public class AspectjAdvisor {
/**
* "*" 代表單個元素,(一個單詞,或一個字母,".." 表示任意個元素) 任意公共方法的執行: execution(public * *(..))
* 任何一個名字以“set”開始的方法的執行: execution(* set*(..)) AccountService接口定義的任意方法的執行:
* execution(* com.xyz.service.AccountService.*(..)) 在service包中定義的任意方法的執行:
* execution(* com.xyz.service.*.*(..)) 在service包或其子包中定義的任意方法的執行:
* execution(* com.xyz.service..*.*(..))
* */
/**###################################################*/
/**before 不帶參數的前置增強*/
@Before(value="execution(* sellerBefore(..))")
public void beforeAdvisor(){
System.out.println("in advisor beforeAdvisor");
}
/** before 帶參數的前置增強,參數要與目標類中要調用的方法名相同,多個參數用逗號隔開*/
@Before(value = "execution(* sellerBeforeParam(..)) && args(name)", argNames = "name")
public void beforeAdvisorParam(String name) {
System.out.println("in advisor beforeAdvisorParam--->" + name);
}
/**
* 在每一個advice方法中都配置切點表達式過於麻煩,可以標註一個公共的切點函數,
* 用以描述切點信息,沒有返回值,只做標註使用,其他的標註了@befor,@afterreturning等的方法 就可以在value屬性中直接調用了
* */
@Pointcut(value = "execution(* sellerCommonMethod(..)) && args(name)", argNames = "name")
public void markMethod(String name) {
}
/** 調用上面統一的切點表達式 */
@Before(value = "markMethod(name)", argNames = "name")
public void commonMethod(String name) {
System.out.println("in advisor commonMethod--->" + name);
}
/**after增強*/
@After(value="execution(* sellerAfter(..))")
public void afterAdvisor(){
System.out.println("in advisor afterAdvisor");
}
/**afterThrowing 拋出異常增強*/
@AfterThrowing(value="execution(* sellerAfterThrowing(..))",throwing="exception")
public void afterThrowingAdvisor(Exception exception ){
System.out.println("in advisor afterThrowingAdvisor--->"+exception);
}
/** #################################################################### **/
/**
* 後置返回增強
*
* @AfterReturning( value="切入點表達式或命名切入點",
* pointcut="和value同義,會覆蓋value",
* argNames="參數列表參數名",
* returning="目標方法的返回值")
*
* */
@AfterReturning(value="execution(* sellerAfterReturn(..))",
argNames="name",returning="name")//目標方法加一個入參會怎樣?
public void afterReturn(String name) {
System.out.println("in advisor afterReturn--->"+name);
}
/**around 增強,這個比較特殊,
* @throws Throwable */
@Around(value="execution(* sellerAround(..))")
public Object aroundAdvisor(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("in advisor aroundAdvisor before");
Object retVal = pjp.proceed(new Object[] {});
System.out.println("in advisor aroundAdvisor end");
return retVal;
}
}
三:IOC容器配置文件(這裏配置了倆個,爲了把不同的功能分開,看的更清楚)也可以用註解的方式
applicationContext1.xml
<?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:jaxws="http://cxf.apache.org/jaxws"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
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://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:component-scan base-package="dao,model,service,client,advice" />
<!--目標bean -->
<bean id="seller" class="aopAspectj.Seller"></bean>
<!--使用了aspectj註解的切面類 -->
<bean class="aopAspectj.AspectjAdvisor"></bean>
<!--自動代理創建器,自動將標註了 @aspectj註解的切面類 植入目標bean中-->
<!--引入了aop命名空間的話可以用 <aop:aspectj-autoproxy />代替 -->
<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"></bean>
</beans>
applicationContext2.xml
<?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:jaxws="http://cxf.apache.org/jaxws"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
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://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:component-scan base-package="dao,model,service,client,advice" />
<!--基於aop的aspectj的配置方式 .下面aop標籤有個 proxy-target-class爲false表示使用jdk的動態代理進行 植入增強-->
<aop:aspectj-autoproxy proxy-target-class="true" />
<!--目標bean -->
<bean id="seller" class="aopAspectj.Seller"></bean>
<!--使用了aspectj註解的切面類 -->
<bean class="aopAspectj.AspectjAdvisor"></bean>
</beans>
三:測試類
package aopAspectj;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.aop.aspectj.annotation.AspectJProxyFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AspectjTest {
/**before 代碼的方式生成目標類的代理*/
@Test
public void test1() {
Seller Seller = new Seller();
// aspectj工廠
AspectJProxyFactory factory = new AspectJProxyFactory();
// 設置目標對象
factory.setTarget(Seller);
// 添加切面類 此處的切面類AspectjAdvisor必須是標註了@aspectj註解的切面類
factory.addAspect(AspectjAdvisor.class);
// 生成植入切面的代理對象
Seller proxy = factory.getProxy();
proxy.sellerBeforeParam("zhangsan");
}
/**before 配置文件的方式*/
@Test
public void test2() {
ApplicationContext context=new ClassPathXmlApplicationContext("aopAspectj/applicationContext1.xml");
Seller Seller=(Seller)context.getBean("seller");
Seller.sellerBeforeParam("zhangsan");
}
/**before 使用aop命名空間的配置(就是不用配置自動代理bean了,以一個aop元素代替了)*/
@Test
public void test3(){
ApplicationContext context=new ClassPathXmlApplicationContext("aopAspectj/applicationContext2.xml");
Seller seller=(Seller)context.getBean("seller");
seller.sellerBeforeParam("zhangsan");
}
/**before 不在@before(value="")中配置切點,而是把切點配置在一個公共的標記方法中,其他標註了@before,@around
*的切點註解中,再value屬性中直接調用這個方法
* */
@Test
public void test4(){
ApplicationContext context=new ClassPathXmlApplicationContext("aopAspectj/applicationContext2.xml");
Seller seller=(Seller)context.getBean("seller");
seller.sellerCommonMethod("zhangsan");
}
/**before 不帶參數 advice增強*/
@Test
public void test5(){
ApplicationContext context=new ClassPathXmlApplicationContext("aopAspectj/applicationContext2.xml");
Seller seller=(Seller)context.getBean("seller");
seller.sellerBefore();
}
/**before 帶參數的advice增強*/
@Test
public void test6(){
ApplicationContext context=new ClassPathXmlApplicationContext("aopAspectj/applicationContext2.xml");
Seller seller=(Seller)context.getBean("seller");
seller.sellerBeforeParam("zhangsan");
}
/**after增強*/
@Test
public void test7(){
ApplicationContext context=new ClassPathXmlApplicationContext("aopAspectj/applicationContext2.xml");
Seller seller=(Seller)context.getBean("seller");
seller.sellerAfter();
}
/**afterThrowing增強
* @throws Exception */
@Test
public void test8() throws Exception{
ApplicationContext context=new ClassPathXmlApplicationContext("aopAspectj/applicationContext2.xml");
Seller seller=(Seller)context.getBean("seller");
seller.sellerAfterThrowing();
}
/**afterReturn 增強*/
@Test
public void test9(){
ApplicationContext context=new ClassPathXmlApplicationContext("aopAspectj/applicationContext2.xml");
Seller seller=(Seller)context.getBean("seller");
seller.sellerAfterReturn("lisi");
}
/**around 增強*/
@Test
public void test10(){
ApplicationContext context=new ClassPathXmlApplicationContext("aopAspectj/applicationContext2.xml");
Seller seller=(Seller)context.getBean("seller");
seller.sellerAround();
}
}