上一節(jié)介紹了基于Schema的AOP夭委,本篇介紹基于@AspectJ
的AOP停做。
1.@AspectJ切面
- 目標(biāo)對(duì)象
package com.lyc.cn.v2.day07;
public interface Animal {
void sayHello();
}
package com.lyc.cn.v2.day07;
public class Dog implements Animal {
public void sayHello() {
System.out.println("--被增強(qiáng)的方法");
}
}
- 引介
package com.lyc.cn.v2.day07;
public interface IIntroduce {
void sayIntroduce();
}
package com.lyc.cn.v2.day07;
public class IntroduceImpl implements IIntroduce {
@Override
public void sayIntroduce() {
System.out.println("--引入");
}
}
- 切面
package com.lyc.cn.v2.day07;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
/**
* 切面類
* @author: LiYanChao
* @create: 2018-10-31 15:46
*/
@Aspect
public class DogAspect {
/**
* 例如:execution (* com.sample.service.impl..*.*(..)
* 1丈钙、execution(): 表達(dá)式主體陈惰。
* 2疏咐、第一個(gè)*號(hào):表示返回類型扬舒,*號(hào)表示所有的類型阐肤。
* 3、包名:表示需要攔截的包名讲坎,后面的兩個(gè)點(diǎn)表示當(dāng)前包和當(dāng)前包的所有子包孕惜,
* 即com.sample.service.impl包、子孫包下所有類的方法晨炕。
* 4衫画、第二個(gè)*號(hào):表示類名,*號(hào)表示所有的類瓮栗。
* 5削罩、*(..):最后這個(gè)星號(hào)表示方法名,*號(hào)表示所有的方法费奸,后面括弧里面表示方法的參數(shù)鲸郊,兩個(gè)點(diǎn)表示任何參數(shù)。
**/
@Pointcut("execution(* com.lyc.cn.v2.day07.*.*(..))")
public void test() {
}
@Before("test()")
public void beforeTest() {
System.out.println("==前置增強(qiáng)");
}
@After("test()")
public void afterTest() {
System.out.println("==后置最終增強(qiáng)");
}
@AfterThrowing("test()")
public void afterThrowingTest() {
System.out.println("==后置異常增強(qiáng)");
}
@AfterReturning("test()")
public void afterReturningTest() {
System.out.println("==后置返回增強(qiáng)");
}
@Around("test()")
public Object aroundTest(ProceedingJoinPoint p) {
System.out.println("==環(huán)繞增強(qiáng)開始");
Object o = null;
try {
o = p.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("==環(huán)繞增強(qiáng)結(jié)束");
return o;
}
@DeclareParents(value = "com.lyc.cn.v2.day07.Dog", defaultImpl = IntroduceImpl.class)
private IIntroduce iIntroduce;
}
- 配置文件
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--
1货邓、proxy-target-class
如果被代理的目標(biāo)對(duì)象至少實(shí)現(xiàn)了一個(gè)接口,則會(huì)使用JDK動(dòng)態(tài)代理四濒,所有實(shí)現(xiàn)該目標(biāo)類實(shí)現(xiàn)的接口都將被代理
如果該目標(biāo)對(duì)象沒有實(shí)現(xiàn)任何接口换况,則創(chuàng)建CGLIB動(dòng)態(tài)代理职辨。
但是可以通過(guò)proxy-target-class屬性強(qiáng)制指定使用CGLIB代理,
2戈二、expose-proxy
解決目標(biāo)對(duì)象內(nèi)部的自我調(diào)用無(wú)法實(shí)施切面增強(qiáng)的問(wèn)題
-->
<aop:aspectj-autoproxy proxy-target-class="true">
<!-- 指定@Aspect類舒裤,支持正則表達(dá)式,符合該表達(dá)式的切面類才會(huì)被應(yīng)用-->
<aop:include name="dogAspect"></aop:include>
</aop:aspectj-autoproxy>
<!--bean-->
<bean id="dog" class="com.lyc.cn.v2.day07.Dog"/>
<!--AspectJ-->
<bean name="dogAspect" class="com.lyc.cn.v2.day07.DogAspect"/>
</beans>
- 測(cè)試及結(jié)果
package com.lyc.cn.v2.day07;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
@Test
public void test1() {
// 基于@AspectJ注解方式
ApplicationContext ctx = new ClassPathXmlApplicationContext("v2/day07.xml");
Dog dog = ctx.getBean("dog", Dog.class);
dog.sayHello();
}
@Test
public void test2() {
// 引入
ApplicationContext ctx = new ClassPathXmlApplicationContext("v2/day07.xml");
// 注意:getBean獲取的是dog
IIntroduce introduce = ctx.getBean("dog", IIntroduce.class);
introduce.sayIntroduce();
}
}
// 測(cè)試一
==環(huán)繞增強(qiáng)開始
==前置增強(qiáng)
--被增強(qiáng)的方法
==環(huán)繞增強(qiáng)結(jié)束
==后置最終增強(qiáng)
==后置返回增強(qiáng)
// 測(cè)試二
--引入
2.總結(jié)
前篇和本篇主要還是回顧了SpringAop的使用方式觉吭,也為了接下來(lái)的源碼分析做好測(cè)試類準(zhǔn)備腾供,在接下來(lái)的分析中主要講解以@AspectJ
方式的實(shí)現(xiàn)方式。