由于环绕通知有前置通知和后置通知结合特优点,所以这里只说环绕通知。实际上是我测试了好久前置通知,总是有错,就放弃了,以后遇到了再说…
切点带参数
如果切点中存在参数,若需要只拦截这个方法,execution
中的参数需要配置全类名,如:
public Integer delete(String userId, Double type) {
System.out.println(userId);
System.out.println(type);
return 100;
}
<aop:pointcut expression="execution(Integer com.spring.aopxml.UserDaoImpl.delete
(java.lang.String, java.lang.Double))" id="cut1"/>
环绕通知中获得切点的参数
public class UserDaoImpl implements UserDao {
public Integer delete(String userId, Double type) {
System.out.println("delete : " + userId);
System.out.println("delete : " + type);
return 100;
}
public Boolean delete(Double type, String userId) {
System.out.println("delete : " + userId + " " + type);
return true;
}
}
import org.aspectj.lang.ProceedingJoinPoint;
public class MyAspectJ {
public Integer around(ProceedingJoinPoint pjp) throws Throwable {
//获得参数
Object[] args = pjp.getArgs();
for(Object o : args)
System.out.println("args " + o);
if((Double)args[1] < 100.0)
return null;
//执行切点
Integer proceed = (Integer)pjp.proceed();
return proceed;
}
}
<bean id="userDao" class="com.spring.aopxml.UserDaoImpl"></bean>
<bean id="myAspectJ" class="com.spring.aopxml.MyAspectJ"></bean>
<aop:config>
<aop:pointcut expression="execution(Integer com.spring.aopxml.UserDaoImpl.delete(java.lang.String, java.lang.Double))" id="cut1"/>
<aop:aspect ref="myAspectJ">
<aop:around method="around" pointcut-ref="cut1" />
</aop:aspect>
</aop:config>
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao ud = (UserDao)ac.getBean("userDao");
Integer delete = ud.delete("11", 100.0);
System.out.println(delete);
/*Console
* args 11
args 100.0
delete : 11
delete : 100.0
100 * */
}
}
环绕通知中获得切点的类型
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
public class MyAspectJ {
public Integer around(ProceedingJoinPoint pjp) throws Throwable {
//获得切点方法的方法签名
//有接口是接口上的方法签名,没有接口时是类上的方法签名
Signature signature = pjp.getSignature();
System.out.println(signature);
//获得切点所在的实例
Object target = pjp.getTarget();
System.out.println(target);
//执行切点
Integer proceed = (Integer)pjp.proceed();
return proceed;
}
}
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
/*
* 如果userDao对应的类有接口,这里不能使用UserDaoImpl,因为Spring的AOP底层在实现动态代理时,
* 如果bean存在接口,则使用JDK动态代理,这样创建的实例是和原接口实例同级别的。
* 如果bean不存在接口,会使用Cglib动态代理,这样创建的类是bean的子类,可以是使用bean接受
* */
UserDao ud = (UserDao)ac.getBean("userDao");
Integer delete = ud.delete("11", 100.0);
System.out.println(delete);
/*Console
* Integer com.spring.aopxml.UserDao.delete(String,Double)
com.spring.aopxml.UserDaoImpl@56a6d5a6
delete : 11
delete : 100.0
100 * */
}
}