`
kanpiaoxue
  • 浏览: 1782129 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Spring mvc controller AOP 失效问题

 
阅读更多

 

 http://stackoverflow.com/questions/17834958/spring-aop-is-not-working-in-with-mvc-structure?rq=1 

You are here: Home » Development » Spring AOP Advice on Annotated Controllers

Spring AOP Advice on Annotated Controllers

Paco | April 2, 2013 1 Comment

AOP DefinitionSpring AOP (Aspect-oriented programming) framework is used to modularize cross-cutting concerns in aspects. If you want a more simple definition you can think of them as a Interceptor but with more options configurations possible.  In Spring there are two different constructs that get called “interceptors”. First, there are Handler Interceptors, which are part of the Spring MVC framework (and similar to Interceptors in Struts 2), and give you the ability to add interceptor logic to requests.  But you also have Method Interceptors, which are part of the Spring AOP framework. These are much more general mechanism than Handler Interceptors, but also potentially more complex. In AOP terminology, such interceptors provide a means of coding the “aspects” you’re talking about.

In this article we are not going to cover how Spring AOP work, I am going to present the solution to an error that could appear when you want to use advices with controller methods in Spring 3 using annotation and non declarative configurations.

¿What is the problem?

You need to make some processing (before and/or after) the execution of a controller. You want to use the AspectJ annotation in Spring to do that. Your code could be something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Controller 
public class TestController { 
 
@RequestMapping("/test.fo") 
public String test(ModelMap model) 
 
{ 
 
model = new ModelMap(); 
 
return "test.jsp"; 
 
}
}

The aspect has to include an advice which will be executed before and after the controller is invoked by a request. Using annotation your aspect could be something similar to:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Aspect
public class StateAspectImpl extends StateAspectI{
 
private static final Log LOG = LogFactory.getLog(StateAspectImpl.class);
 
@Pointcut("within(@org.springframework.stereotype.Controller *)") //we define a pointcut for all controllers
public void classPointcut() {}
 
@Pointcut("execution(* *getViewNew(..))") // the methods that ends in getViewNew are join to this pointcut
public void methodPointcut() {}
 
/**
* Operations*/
 
@Around("classPointcut() && methodPointcut() && args(request,modelMap)")
public ModelMap recoverStateView(ProceedingJoinPoint joinPoint, HttpServletRequest request, ModelMap modelMap) throws Throwable {
 
//the operations that you want execute
 
}

So you want to advice all the methods that contains getViewNew in the name from all classes annotated with @Controller. When you execute this code deploying the app in a server it doesn’t work and don’t raise any error or exception.

The cause is…

After debugging the code I realized that the advice is never been executed. So I tried to look for a solution in StackOverflow. Some of the question/answer that I find there were:

http://stackoverflow.com/questions/3310115/spring-aop-advice-on-annotated-controllers

http://stackoverflow.com/questions/789759/how-can-i-apply-an-aspect-using-annotations-in-spring

http://stackoverflow.com/questions/9310927/aspect-not-executed-in-spring

But anyone of these discussion and the solutions that are proposed in, works in my situation. The question that point me in the right direction was:

http://stackoverflow.com/questions/3991249/how-can-i-combine-aspect-with-controller-in-spring-3

The source of the problem is: Spring AOP is based on a proxy generation, that executed the advices in the pointcuts that you declare.For accomplish this, the classes that contain the methods that match with the pointcuts which you created (the classes we want to intercept the execution) have to be declared with component scanning in the domain on the DispatcherServlet.

At this point, if your using a xml file to describe the dispatched servlet, like

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
 
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
 
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

for the web.xml file, and:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
 
<!-- not strictly necessary for this example, but still useful, see http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-ann-controller for more information -->
<context:component-scan base-package="springmvc.web" />
 
<!-- the mvc resources tag does the magic -->
<mvc:resources mapping="/resources/**" location="/resources/" />
 
<!-- also add the following beans to get rid of some exceptions -->
<bean />
<bean
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
</bean>
 
<!-- JSTL resolver -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
 
</beans>
for the spring servlet configuration file, the solution works without problem and the advice is executed before and after the method on the Controller classes.

But, what happen if you don’t have a dispatcher servlet XML file and you are using a class that extends WebMvcConfigurerAdapter to create the servlet configuration. In this case the advice is never executed because the controllers are not created in the domain of the DispatcherServlet.

The solution is…

There are two possible solutions to this problem:

  1. Change the configuration of your spring application to use a xml configuration instead of the WebMvcConfigurerAdapter.
  2. Create a aop xml file to declare the class that implement the advice and to configure the aop proxy to make use of this advice.
I recommended the second solution in the case in which you were using programmatic configuration of Spring instead of declarative. In that case the xml file could be:
 
1
2
3
4
5
6
7
8
9
10
11
12
13
<?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'
xsi:schemaLocation='http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd'>
 
<!-- AOP support -->
<bean id='stateAspectImpl' class='...ui.aspect.StateAspectImpl' />
<aop:aspectj-autoproxy>
<aop:include name='stateAspectImpl' />
 
</aop:aspectj-autoproxy>
 
</beans>

The disadvantage of this solution is: each time you have to create a new advice, you have to remember change the xml file to declare the advice and  add the advice to the proxy.

——————————————–

References:

Spring AOP Reference Documentation.

Article in Java Geek Codes: a quick tutorial with full code.

http://stackoverflow.com/questions/3310115/spring-aop-advice-on-annotated-controllers

http://stackoverflow.com/questions/789759/how-can-i-apply-an-aspect-using-annotations-in-spring

http://stackoverflow.com/questions/9310927/aspect-not-executed-in-spring

http://stackoverflow.com/questions/3991249/how-can-i-combine-aspect-with-controller-in-spring-3

http://stackoverflow.com/questions/1483063/spring-mvc-3-and-handling-static-content-am-i-missing-something

 

 

Tags: aopfeaturedjavaspring

CategoryDevelopmentJava

分享到:
评论

相关推荐

    springMVC AOP拦截拦截Controller等实现日志管理

    通过这种方式,我们可以在Spring MVC中利用AOP实现对Controller方法的透明日志管理,不仅记录正常流程,也能捕获和记录异常,提升系统的可维护性和问题排查效率。 在实际项目中,我们可以根据需求进一步定制日志...

    spring_mvc企业级框架精简版本,纯注解,绝对原创(最新版本,之前连接失效了)

    11. **AOP(面向切面编程)**:Spring MVC可以利用Spring的AOP支持实现日志记录、事务管理等跨切面的关注点。 12. **验证(Validation)**:Spring MVC可以配合JSR 303/349的Bean Validation进行数据校验,使用`@...

    springMVC+hibernate+spring4.3 jar包整合

    首先,Spring MVC是Spring框架的一个模块,它专门用于构建Web应用程序的Model-View-Controller(MVC)架构。Spring MVC通过解耦业务逻辑、数据模型和用户界面,提供了灵活的控制层设计。它的主要功能包括请求映射、...

    shiro整合spring+springmvcjar包

    - Spring的JAR包:`spring-context`、`spring-beans`、`spring-aop`,用于Spring的依赖注入和AOP支持。 - Spring MVC的JAR包:`spring-webmvc`,提供Web MVC功能。 - 可能还需要`slf4j-api`和相应的日志实现库,...

    Spring In Action 随书源码

    2. **Spring MVC**:Spring的Model-View-Controller(MVC)架构为Web应用提供了强大的支持,包括控制器、模型对象、视图解析等,简化了Web应用的开发。 3. **AOP**:Spring的AOP模块支持声明式事务管理、日志记录、...

    Spring-Reference_zh_CN(Spring中文参考手册)

    2.5.1. Spring MVC的表单标签库 2.5.2. Spring MVC合理的默认值 2.5.3. Portlet 框架 2.6. 其他特性 2.6.1. 动态语言支持 2.6.2. JMX 2.6 .3. 任务规划 2.6.4. 对Java 5(Tiger)的支持 2.7. 移植到Spring 2.0 ...

    16.spring与springmvc常见面试题.docx

    原理:AOP 是面向切面编程,是通过动态代理的方式为程序添加统一功能,集中解决一些公共问题。好处:1.各个步骤之间的良好隔离性耦合性大大降低、2.源代码无关性,再扩展功能的同时不对源码进行修改操作。 2. ...

    BlazeDS+Spring+SpringMVC 注解方式配置文件

    SpringMVC 是Spring框架的一部分,是一个用于构建Web应用的MVC(Model-View-Controller)架构。 在"BlazeDS+Spring+SpringMVC 注解方式配置文件"的场景下,我们将关注如何使用注解来简化这三者之间的整合。注解是...

    基于SSM和Bootstrap的用户管理系统

    2. **Spring MVC**:作为Spring框架的一部分,Spring MVC是一个用于构建Web应用程序的模型-视图-控制器(Model-View-Controller, MVC)架构。它处理HTTP请求,将请求转发给相应的处理器,然后将处理结果返回给客户端...

    Struts-Hibernate-Spring推荐的最优组合配置

    它们各自专注于应用程序的不同层次:Struts在表现层提供MVC(Model-View-Controller)架构,Hibernate处理持久层对象与数据库之间的交互,而Spring则是一个全面的后端解决方案,涵盖了依赖注入、AOP(面向切面编程)...

    Struts2.2.3 Spring3.0.5 Hibernate3.6.5 sql server整合实例源码呈现

    Struts2是基于MVC(Model-View-Controller)设计模式的开源Web应用框架,它解决了传统Struts1的一些问题,提供了更强大的控制结构和更丰富的拦截器。在Struts2.2.3版本中,你可以期待更好的性能和增强的可扩展性,...

    com.springsource相关jar包

    SpringSource提供的jar包可能包含了Spring的核心模块,如IoC(Inversion of Control)容器,AOP框架,MVC(Model-View-Controller)支持,以及数据访问层的工具,如JDBC抽象层和ORM集成。 Spring框架的核心概念包括...

    SSM+Shiro权限控制

    Spring是一个全面的后端开发框架,它提供依赖注入(DI)和面向切面编程(AOP),用于简化应用的配置和管理。Spring MVC是Spring框架的一部分,专门处理Web层的请求和响应,负责将用户请求转发到相应的业务逻辑处理。...

    一年前整合flex3+cairngorm+spring+hibernate

    2. **Cairngorm**:Cairngorm是Adobe官方推荐的一种轻量级的MVC(Model-View-Controller)设计模式,用于Flex和ActionScript项目。Cairngorm提供了一种结构化的方式来组织代码,使得应用更易于维护和扩展。它包括了...

    java面试题

    7:Spring MVC:分离模型、视图、控制器、以便更容易定制 折构函数和虚函数? 答:折构函数式销毁一个类的函数,虚函数是为了C++的动态绑定而设计的。 描述你的编程风格? 答:类名首字母大写,常量一般全部大写,...

    SpringMVCHibernate集成及常见问题总结

    - **缓存问题**:Ehcache的配置可能导致缓存失效、更新不及时等问题。 - **资源文件**:国际化消息文件的路径和编码设置不当可能导致国际化功能失效。 在后续的项目中,可以进一步完善这个脚手架,如添加AOP缓存...

    ssh企业级框架精简版本,纯注解,绝对原创(最新版本,之前连接失效了)

    1. Spring:Spring是一个全面的后端应用框架,提供了依赖注入(DI)和面向切面编程(AOP)的核心特性。在精简版中,Spring可能通过注解如@Service、@Repository和@Controller来简化bean的定义,避免XML配置。同时,...

    cxf jar 包下载

    Spring MVC(Model-View-Controller)是Spring框架的一部分,专门用于构建Web应用。通过结合CXF和Spring MVC,开发者可以轻松地创建基于HTTP的Web服务,同时利用Spring的强大功能进行依赖注入、AOP(面向切面编程)...

    ssm企业级框架精简版本,纯注解,绝对原创(最新版本,之前连接失效了)

    首先,Spring框架是核心,它提供了依赖注入(DI)和面向切面编程(AOP)的功能。DI使得对象之间的依赖关系可以被外部容器管理,而不是硬编码在类内部,这增强了代码的可测试性和可维护性。AOP则允许我们定义横切关注点,...

    s2sh整合程序

    Struts2、Hibernate和Spring(简称S2SH)是Java Web开发中的一种经典组合,用于构建基于MVC(Model-View-Controller)架构的应用程序。这个整合程序涉及到这三大框架的协同工作,以实现数据持久化、业务逻辑处理以及...

Global site tag (gtag.js) - Google Analytics