Around环绕通知
对于其他四种通知联合使用的时候共享参数必须要传递一个参数变量,现在就不太友好。
Around方式与更像是其他几种方式的联合体
切面类
package com.xbz.learn.spring.aspect;
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.springframework.stereotype.Component;
/**
* 切面类
* @author xubaozhong
*
*/
@Aspect
public class FirstAspect {
@Pointcut("execution (* com.xbz.learn.spring.aspect.FirstAspectTarget.*(..))")
public void pointcut(){
}
@Around("pointcut()")
public void doAround(ProceedingJoinPoint jp){
Throwable ex=null;
try{
System.out.println("doBefore...");
jp.proceed();
}catch(Throwable e){
ex=e;
System.out.println("doAfterThrowing...");
}finally{
System.out.println("doAfter...");
}
if(ex==null){
System.out.println("doAfterReturning...");
}
}
}
目标类
package com.xbz.learn.spring.aspect;
import org.springframework.stereotype.Component;
/**
* 切面目标类,被拦截的目标类
* @author xubaozhong
*
*/
@Component
public class FirstAspectTarget {
/*public void doService(){
System.out.println("doService----处理业务逻辑");
}*/
public void doService(User user){
System.out.println(user);
// throw new RuntimeException(new Exception("业务报错"));
}
}
JavaConfig
package com.xbz.learn.spring.aspect;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
//@ComponentScan
@EnableAspectJAutoProxy
public class FirstAspecJavaConfig {
@Bean
public FirstAspect getFirstAspect(){
return new FirstAspect();
}
@Bean
public FirstAspectTarget getFirstAspectTarget(){
return new FirstAspectTarget();
}
}
Test类
package com.xbz.learn.spring.aspect;
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;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={FirstAspecJavaConfig.class})
public class FirstAspectTest {
@Autowired
private FirstAspectTarget target;
@Test
public void testFirstAspect(){
User user = new User();
user.setUsername("");
target.doService(user);
}
}
class User{
@Override
public String toString() {
return "User [username=" + username + ", password=" + password + "]";
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
private String username;
private String password;
}
案例中模仿了Before | After |AfterReturning|AfterThrowing的调用模式。证明Around完全可以等价于前4中通知,只是这样在切面方法中处理太复杂。有利必有弊。
XML替代JavaConfig方案
<?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:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
">
<!-- 使用CGLIB代理创建代理对象,默认使用JDK代理 -->
<aop:aspectj-autoproxy proxy-target-class="false"></aop:aspectj-autoproxy>
<!-- 切面类 -->
<bean id="aspectBean" class="com.xbz.learn.spring.aspect.FirstAspect"></bean>
<!-- 目标类 -->
<bean id="targetBean" class="com.xbz.learn.spring.aspect.FirstAspectTarget"></bean>
<aop:config>
<aop:aspect ref="aspectBean">
<aop:pointcut expression="execution (* com.xbz.learn.spring.aspect.FirstAspectTarget.*(..))" id="pt"/>
<aop:around method="doAround" pointcut-ref="pt"/>
</aop:aspect>
</aop:config>
</beans>