1. 程式人生 > >Spring整合aspectj框架實現的aop

Spring整合aspectj框架實現的aop

Spring整合aspectj框架實現的aop

在現在的開發中使用這種方案比較多.

spring2.0以後它支援jdk1.5註解,而整合aspectj後可以使用aspectj語法,可以簡化開發。

Aspect:切面 =切點+通知(多個切點與多個通知的組合)

AspectJ它是一個第三方框架,spring2.0後可以使用aspectJ框架的部分語法.

AspectJ框架它定義的通知型別有6

1.前置通知Before相當於BeforeAdvice

2.後置通知AfterReturning相當於AfterReturningAdvice

3.環繞通知 Around 相當於MethodInterceptor

4.丟擲通知AfterThrowing相當於ThrowAdvice

5.引介通知DeclareParents相當於IntroductionInterceptor

6.最終通知After不管是否異常,該通知都會執行

相比spring的傳統AOP Advice多了一個最終通知

第一步:建立目標(target)
public class UserServiceImpl implements UserService {

	@Override
	public int add() {
		int a = 10 / 0;
		System.out.println("add......");
		return 66;
	}

	@Override
	public void del() {
		System.out.println("del......");
	}

	@Override
	public void update() {
		System.out.println("update......");
	}

	@Override
	public void find() {
		System.out.println("find......");
	}

}

第二步:建立通知(增強  advice)

注意:aspectj中它的增強可以不實現任何介面,只需要定義出增強功能(方法)

//advice
public class UserServiceHelper{
	//前置通知+引數
	public void before(JoinPoint jp){
		System.out.println("攔截的目標類" + jp.getSignature().getDeclaringTypeName());
		System.out.println("攔截的方法" + jp.getSignature().getName());
		System.out.println("前置......");
	}
	//後置通知
	public void after(JoinPoint jp , Object val){
		System.out.println("返回值為" + val);
		System.out.println("後置.....");
	}
	//環繞通知
	public Object around(ProceedingJoinPoint pip) throws Throwable{
		System.out.println("環繞前");
		Object proceed = pip.proceed();
		System.out.println("環繞後");
		return proceed;
	}
	//異常丟擲通知
	public void afterThrowing(JoinPoint jp,Throwable ex){
		System.out.println(ex);
		System.out.println("發現異常");
	}
	//最終通知
	public void end(JoinPoint jp){
		System.out.println(jp.getSignature().getName());
		System.out.println("結束");
	}
第三步:springxml配置檔案中來配置

<aop:config>下的<aop:aspect>aspectJ框架用來宣告切面的。

applicationContext.xml配置檔案

<aop:config>
	<aop:aspect ref="userServiceAdvice">
		<aop:pointcut expression="execution(* com.itheima.aspectj.* .*(..))" id="myPointCut"/>
		<aop:before method="before" pointcut-ref="myPointCut" />       前置
		<aop:after-returning method="after" pointcut-ref="myPointCut" />	後置
		<aop:around method="around" pointcut-ref="myPointCut"/>		環繞
		<aop:after-throwing method="afterThrowing" pointcut-ref="myPointCut"/>	發現異常
		<aop:after method="end" pointcut-ref="myPointCut"/>			最終
	</aop:aspect>
</aop:config>
測試程式碼
//前置通知
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class AspectjTest {
	@Autowired
	private UserService userService;
	@Test
	public void test(){
		userService.del();
	}
加引數
public class UserServiceHelper {
	//前置通知+引數
	public void before(JoinPoint jp){
		System.out.println("攔截的目標類" + jp.getSignature().getDeclaringTypeName());
		System.out.println("攔截的方法" + jp.getSignature().getName());
		System.out.println("前置......");
	}
	//後置通知
	public void after(JoinPoint jp , Object val){
		System.out.println("返回值為" + val);
		System.out.println("後置.....");
	}
	//環繞通知
	public Object around(ProceedingJoinPoint pip) throws Throwable{
		System.out.println("環繞前");
		Object proceed = pip.proceed();
		System.out.println("環繞後");
		return proceed;
	}
	//異常丟擲通知
	public void afterThrowing(JoinPoint jp,Throwable ex){
		System.out.println(ex);
		System.out.println("發現異常");
	}
	//最終通知
	public void end(JoinPoint jp){
		System.out.println(jp.getSignature().getName());
		System.out.println("結束");
	}

applicationContext.xml
<aop:config>
	<aop:aspect ref="userServiceAdvice">
		<aop:pointcut expression="execution(* com.itheima.aspectj.* .*(..))" id="myPointCut"/>
		<aop:before method="before" pointcut-ref="myPointCut" />		前置					
		<aop:after-returning method="after" pointcut-ref="myPointCut" returning="val" />  後置
		<aop:around method="around" pointcut-ref="myPointCut"/>		環繞
		<aop:after-throwing method="afterThrowing" pointcut-ref="myPointCut"  throwing="ex"/>  發現異常
		<aop:after method="end" pointcut-ref="myPointCut"/>	最終
	</aop:aspect>
</aop:config>


關於代理方式選擇

springaop開發中,它使用的是代理方案,代理實現有兩種:

1.     jdkproxy

2.     cglib

spring框架預設情況下,會對有介面的類使用proxy代理。沒有介面的類使用cglib代理

如果為false  那麼如果有實現介面那麼為jdkproxy 沒有介面則為cglib

如果為true   那麼不管有沒有實現介面預設為cglib

Proxy-target-class的值預設是false,它代表有介面使用proxy代理

問題:如果現在對目標要使用cglib代理(不考慮是否有介面)

只需要將proxy-target-class設定為true.