SpringMVC杂记(十五) spring-mvc controller 的切面
程序员文章站
2022-07-15 14:41:53
...
SpringMVC杂记(十五) spring-mvc controller 的切面
一)对一般Spring上下文管理的bean,配合切面表达式都可以对其做拦截操作,原理是Spring在启动的时候,利用字节码技术生成了其子类,
这样就把切面逻辑“织入”到bean之中了。这个用spring的人一般都懂。但是很多人发现,spring-mvc使用起来,controller的代码不能通过这种
方式自己织入逻辑。
Spring MVC在启动的时候会根据处理器策略加载handler映射到一个map中,
这个时候因为配置的原因它从容器中取到的对象是原生对象,而不是我们代理的对象;所以不管我们的Controller做了什么操作都不会经过我们的代理,这样AOP就失去了作用。
二)有些情况,确实需要做代理,而且Interceptor有不太好使的时候,我们就要另辟蹊径了。如下代码和配置所示,一样还是可以成功的。缺点就是
切面表达式不好用了,要自己写代码判断方法是不是要拦截。
一)对一般Spring上下文管理的bean,配合切面表达式都可以对其做拦截操作,原理是Spring在启动的时候,利用字节码技术生成了其子类,
这样就把切面逻辑“织入”到bean之中了。这个用spring的人一般都懂。但是很多人发现,spring-mvc使用起来,controller的代码不能通过这种
方式自己织入逻辑。
Spring MVC在启动的时候会根据处理器策略加载handler映射到一个map中,
这个时候因为配置的原因它从容器中取到的对象是原生对象,而不是我们代理的对象;所以不管我们的Controller做了什么操作都不会经过我们的代理,这样AOP就失去了作用。
二)有些情况,确实需要做代理,而且Interceptor有不太好使的时候,我们就要另辟蹊径了。如下代码和配置所示,一样还是可以成功的。缺点就是
切面表达式不好用了,要自己写代码判断方法是不是要拦截。
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor" />
import java.lang.reflect.Method; import org.aopalliance.aop.Advice; import org.aopalliance.intercept.MethodInvocation; import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor; import org.springframework.beans.factory.InitializingBean; @SuppressWarnings({"serial"}) public class SpringMvcControllerAspect extends StaticMethodMatcherPointcutAdvisor implements InitializingBean { // private static final Logger LOGGER = LoggerFactory.getLogger(SpringMvcControllerAspect.class); @Override public boolean matches(Method method, Class<?> targetClass) { // 这里来判断方法是否需要拦截 // 不用切点表达式,自己写代码判断 return false; } @Override public void afterPropertiesSet() throws Exception { super.setOrder(Integer.MAX_VALUE); super.setAdvice(MethodInterceptor.INSTANCE); } // 织入业务逻辑 // ================================================================================================================ private static final class MethodInterceptor implements org.aopalliance.intercept.MethodInterceptor, Advice { public static final Advice INSTANCE = new MethodInterceptor(); public Object invoke(MethodInvocation invocation) throws Throwable { // 前织入 Object result = invocation.proceed(); // 后织入 return result; } } }