spring aop实现对方法进行拦截的几种方式
Spring aop实现的基础是动态代理,jdk代理和cglib代理的区别是,jdk只能代理接口,而cglib代理则也可以代理类(这个我现在也没有弄太明白)
首先给出使用到的几个类
1.
public interface AccountInterface {
public void say();
public void hello();
}
2
public class AccountImpl implements AccountInterface {
@Override
public void say() {
System.out.println("doing");
}
@Override
public void hello() {
System.out.println("hello");
throw new IllegalArgumentException("异常");
}
}
一、使用aopalliance包内的MethodInterceptor类
可在方法内做其他处理
public class SpringMethodInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation invo) throws Throwable {
System.out.println(invo.getMethod().getName());
System.out.println("before");
Object returnObject = invo.proceed();
System.out.println("after");
return returnObject;
}
}
xml配置文件
<beans>
<bean id="loginTarget" class="zhou.AccountImpl"/>
<bean id="SpringMethodInterceptor" class="zhou.SpringMethodInterceptor"/>
<bean id="login" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<ref local="loginTarget"/>
</property>
<property name="proxyInterfaces">
<value>zhou.AccountInterface</value>
</property>
<property name="interceptorNames">
<list>
<idref local="SpringMethodInterceptor"/>
</list>
</property>
</bean>
</beans>
测试
public class Test {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
AccountInterface as = (AccountInterface)ctx.getBean("login");
as.say();
}
}
结果
可以看到MethodInterceptor成功的拦截到了say方法
二、使用Aspect
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
public class TestAspect {
public void doAfter(JoinPoint jp) {
System.out.println("log Ending method: "
+ jp.getTarget().getClass().getName() + "."
+ jp.getSignature().getName());
}
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
long time = System.currentTimeMillis();
Object retVal = pjp.proceed();
time = System.currentTimeMillis() - time;
System.out.println("process time: " + time + " ms");
return retVal;
}
public void doBefore(JoinPoint jp) {
System.out.println("log Begining method: "
+ jp.getTarget().getClass().getName() + "."
+ jp.getSignature().getName());
}
public void doThrowing(JoinPoint jp, Throwable ex) {
System.out.println("method " + jp.getTarget().getClass().getName()
+ "." + jp.getSignature().getName() + " throw exception");
System.out.println(ex.getMessage());
}
}
配置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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<bean id="service" class="zhou.AccountImpl"/>
<bean id="testAspect" class="zhou.TestAspect" />
<aop:config proxy-target-class="true">
<aop:aspect id="aspect" ref="testAspect">
<!--
第一个*代表所有的返回值类型 第二个*代表所有的类 第三个*代表类所有方法 最后一个..代表所有的参数
-->
<aop:pointcut expression="execution(* zhou.*.say(..))" id="pointcut"/>
<aop:before method="doBefore" pointcut-ref="pointcut"/>
<aop:after method="doAfter" pointcut-ref="pointcut"/>
<aop:around method="doAround" pointcut-ref="pointcut"/>
<aop:after-throwing method="doThrowing" throwing="ex" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
</beans>
测试
public class Test {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
AccountInterface as = (AccountInterface)ctx.getBean("service");
as.say();
}
}
结果
三、使用注解配置aspect
同样使用上面的TestAspect类,做如下修改
在类上面添加注解,添加一个方法,加上before注解
配置xml
<context:annotation-config/>
<context:component-scan base-package="zhou"/>
<aop:aspectj-autoproxy/>
<bean id="service" class="zhou.AccountImpl"/>
测试
public class Test {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
AccountInterface as = (AccountInterface)ctx.getBean("service");
as.say();
}
}
结果
上面的这几种方式只是spring aop的最简单的应用,希望能帮到大家