之前上班做spring+spring mvc +hibernate开发, 2年之久不做想复习一下aop的使用,结果配置遇见aop不生效,解决而记录!
先上代码直接看反例效果会明显:
首先看一下我的代码的包路径:
接下来看Spring-MVC的配置文件部分代码:
-
<?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:context="http://www.springframework.org/schema/context"
-
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
-
xmlns:aop="http://www.springframework.org/schema/aop"
-
xsi:schemaLocation="http://www.springframework.org/schema/beans
-
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
-
http://www.springframework.org/schema/aop
-
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
-
http://www.springframework.org/schema/context
-
http://www.springframework.org/schema/context/spring-context-4.0.xsd
-
http://www.springframework.org/schema/tx
-
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
-
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.0.xsd">
-
-
<context:component-scan base-package="cn.edu.neu" />
-
-
-
-
在看一下Spring的配置文件:
-
<?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:context="http://www.springframework.org/schema/context"
-
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
-
xmlns:aop="http://www.springframework.org/schema/aop"
-
xsi:schemaLocation="http://www.springframework.org/schema/beans
-
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
-
http://www.springframework.org/schema/aop
-
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
-
http://www.springframework.org/schema/context
-
http://www.springframework.org/schema/context/spring-context-4.0.xsd
-
http://www.springframework.org/schema/tx
-
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
-
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.0.xsd">
-
-
-
-
-
-
<aop:aspectj-autoproxy expose-proxy="true" />
-
<aop:config proxy-target-class="true">
-
<aop:aspect id="aspectId" ref="aopLog">
-
-
-
expression="execution(* cn.edu.neu.service.*.*(..))" />
-
<aop:before method="before" pointcut-ref="log"/>
-
<aop:after method="after" pointcut-ref="log"/>
-
-
-
-
-
web.xml配置文件如下:
-
<?xml version="1.0" encoding="UTF-8"?>
-
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-
xmlns="http://java.sun.com/xml/ns/javaee"
-
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
-
-
<display-name>Archetype Created Web Application</display-name>
-
-
-
-
-
<param-name>contextConfigLocation</param-name>
-
<param-value>classpath:spring-mybatis.xml</param-value>
-
-
-
-
-
-
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
-
-
-
-
-
-
<filter-name>encodingFilter</filter-name>
-
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
-
<async-supported>true</async-supported>
-
-
<param-name>encoding</param-name>
-
<param-value>UTF-8</param-value>
-
-
-
-
<filter-name>encodingFilter</filter-name>
-
<url-pattern>/*</url-pattern>
-
-
-
-
-
-
<servlet-name>SpringMVC</servlet-name>
-
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
-
-
-
<param-name>contextConfigLocation</param-name>
-
<param-value>classpath:spring-mvc.xml</param-value>
-
-
<load-on-startup>1</load-on-startup>
-
<async-supported>true</async-supported>
-
-
-
<servlet-name>SpringMVC</servlet-name>
-
-
<url-pattern>/</url-pattern>
-
-
-
-
<welcome-file>/index.jsp</welcome-file>
-
-
-
以上的配置之后以为大功告成,结果一运行,恩?不好使?,接下来分析一下原因:
我们知道web.xml中加载顺序是:context-param -> listener -> filter -> servlet ,所以在加载完参数之后开始启动spring的监听器,监听器加载完成之后,就完成了bean加载到容器的过程。但是你可能到现在还没有注意的是,在上面springmvc和spring的配置文件都配置了<context:component-scan base-package="cn.edu.neu" />,所以导致在Spring的DispatcherServlet启动过程中又一次把springmvc.xml扫描到的组件(就是类)再一次添加到spring的容器中,此次会覆盖前面加载的,所以这个就是为什么spring aop不生效的原因!!!
到此是不是还是有点不明白呢?那就在具体说一下:因为在第一次spring加载组件的时候会给pointcut对象生成代理(aop实现原始是动态代理),放到容器中。但是第二次加载时候生成的对象没有代理,第二次覆盖了第一次存在代理的对象,因此导致aop不生效!
接下来说一下解决方案:
方案1:将spring和spring mvc的配置文件放到一个配置文件中,即可避免两次加载覆盖。
方案2:如果非要两个文件都配置扫描的代码的话,那就把需要生成代理的包路径在spring中配置扫描,确保spring mvc的扫描路径不包括“需要生成代理的路径”即可。(而spring mvc的controller组件扫描必要要在spring mvc中配置)
例如方案2代码如下:
spring的配置文件:
扫描非controller路径
-
<?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:context="http://www.springframework.org/schema/context"
-
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
-
xmlns:aop="http://www.springframework.org/schema/aop"
-
xsi:schemaLocation="http://www.springframework.org/schema/beans
-
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
-
http://www.springframework.org/schema/aop
-
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
-
http://www.springframework.org/schema/context
-
http://www.springframework.org/schema/context/spring-context-4.0.xsd
-
http://www.springframework.org/schema/tx
-
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
-
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.0.xsd">
-
-
-
-
-
<context:component-scan base-package="cn.edu.neu.dao,cn.edu.neu.service,cn.edu.neu.log" />
-
-
-
-
-
<aop:aspectj-autoproxy expose-proxy="true" />
-
<aop:config proxy-target-class="true">
-
<aop:aspect id="aspectId" ref="aopLog">
-
-
-
expression="execution(* cn.edu.neu.service.*.*(..))" />
-
-
<aop:before method="before" pointcut-ref="log"/>
-
<aop:after method="after" pointcut-ref="log"/>
-
-
-
-
-
-
spring-mvc配置文件:
spring mvc配置文件只负责扫描contrller的组件
-
<?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:context="http://www.springframework.org/schema/context"
-
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
-
xmlns:aop="http://www.springframework.org/schema/aop"
-
xsi:schemaLocation="http://www.springframework.org/schema/beans
-
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
-
http://www.springframework.org/schema/aop
-
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
-
http://www.springframework.org/schema/context
-
http://www.springframework.org/schema/context/spring-context-4.0.xsd
-
http://www.springframework.org/schema/tx
-
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
-
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.0.xsd">
-
-
-
-
-
<context:component-scan base-package="cn.edu.neu.controller" />
-
核心结论:就是需要生成代理的类一定不要被重复覆盖加载(Spring bean的加载支持覆盖),否则就会aop不起作用!
补充:
你通过配置方案1或者方案2之后,你在eclipse中启动tomcat可能会发现还是加载两次!!!这个问题坑了我一上午,记录一下自己的心得吧!
得到下面结论的运行环境是:
1:Tomcat部署目录默认的webapps,而且webapps中部署了一个该验证的项目。
2:eclipse版本:Version: Mars.1 Release (4.5.1),tomcat版本:apache-tomcat-7.0.53-windows-x64
结论先行:
1:从新解压一个全新的tomcat,然后将项目放到webapps中启动发现只会加载一次,这是就可以确定原因了就是原来tomcat或eclipse的问题!接下来看如下分析:
2:只要你的tomcat配置过eclipse的话,当你使用eclipse启动tomcat之后,会在tomcat的server.xml中生成如下代码:
<Context docBase="C:\install\tmp\apache-tomcat-7.0.53-windows-x641\apache-tomcat-7.0.53\webapps\springaop" path="/neuweb" reloadable="true" source="org.eclipse.jst.jee.server:springaop"/>
从此之后无论你是使用eclipse启动tomcat还是bin/startup.bat启动tomcat都会加载两次bean!(Context docBase只要给项目起别名了的话就会加载两次,但是如果当path的名字和docBase的最后的名字一样的话就不会触发加载两次了,一样的话其实就是起了一个和原来名字一样的别名与没起别名是一样的。)
即如下不如加载两次:
<Context docBase="C:\install\tmp\apache-tomcat-7.0.53-windows-x641\apache-tomcat-7.0.53\webapps\springaop" path="/springaop" reloadable="true" source="org.eclipse.jst.jee.server:springaop"/>
所以到此就可以确定原因了:就是因为项目有别名访问导致最终实现两次加载!
解决办法:删除Context代码之后,使用tomcat脚本启动tomcat,这时候bean就会加载一次!(如果使用eclipse启动tomcat的话还是会生成context,还是加载两次)
context docbase作用:就是你给的项目起一个访问的别名,例如:你有一个叫appweb的项目,这时候就可以使用localhost:8080/appweb访问该项目了,但是如果你还想使用localhost:8080/website路径访问appweb的话,就需要使用context docbase配置。具体配置不细说了,自行找资料学习!
本文转载:https://blog.csdn.net/dax1n/article/details/77131548
相关推荐
本项目是关于"activiti+spring+spring Mvc+mybatis+maven"的整合,旨在创建一个基于Activiti工作流引擎、Spring、Spring MVC、MyBatis以及Maven的开发环境。下面将详细介绍这些技术及其整合过程。 首先,`activiti`...
Maven+Spring+Spring MVC+MyBatis+MySQL,搭建SSM框架环境
总的来说,"spring+spring mvc+mybatis框架整合实现超市货物管理系统"是一个涵盖后端开发基础技能的项目,涉及了JavaEE的多个层面,从Web层的路由处理,到业务逻辑的实现,再到数据库操作,以及用户认证和分页显示等...
Java EE企业级应用开发教程(Spring+Spring MVC+MyBatis)SSM源码Java EE企业级应用开发教程(Spring+Spring MVC+MyBatis)SSM源码Java EE企业级应用开发教程(Spring+Spring MVC+MyBatis)SSM源码Java EE企业级应用...
SSM(spring+spring MVC+mybatis)开发学生信息后台管理系统,实现学生增删改查功能设计一个简单的学生信息管理系统,要求使用SSM框架技术整合实现,用户登录后能够通过Web页面添加、删除、修改和查询学生信息 ...
这份文档名为《Java EE 框架整合开发入门到实战——Spring+Spring MVC+MyBatis(微课版)课后习题答案.pdf》,它显然是关于Java EE中流行的三个框架整合使用的教程。这三个框架分别是Spring、Spring MVC和MyBatis,...
一个简单的spring+struts2+hibernate+mybatis整合(数据库脚本放在项目资源文件的sql目录下) 因为没想好mvc用springmvc好,还是struts2好 所以没有整合进去
Spring+Spring MVC+MyBatis 框架整合案例 Spring 框架是 Java 平台上的一种开源框架,由 Rod Johnson 和 Juergen Hoellerสอง位开发者创建,于 2004 年首次发布。Spring 框架的主要目标是简化企业级应用程序的...
基于Spring + Spring MVC + MyBatis的图书馆管理系统。主要功能包括:图书查询、图书管理、图书编辑、读者管理、图书的借阅与归还以及借还日志记录等。基于Spring + Spring MVC + MyBatis的图书馆管理系统。主要功能...
"Maven+Spring+Spring MVC+Mybatis"的组合是Java Web开发中非常流行的技术栈,它提供了全面的解决方案,涵盖了项目构建、依赖管理、应用层服务、表现层控制以及数据持久化等各个方面。下面将详细阐述这些技术及其在...
SSM(Spring、Spring MVC和MyBatis)是Java Web开发中的主流框架组合,用于构建高效、模块化和可维护的Web应用程序。本整合例子旨在为初学者提供一个全面的起点,帮助理解这三个框架如何协同工作。以下是关于Maven、...
项目描述 学生成绩管理系统,有三...spring boot+spring mvc+mybatis+layui+jquery+thymeleaf http://localhost:8080/Sys/loginView 管理员账号 admin admin 老师登录 2020031920 111111 学生账号登录 20200319 111111
这个"Spring+Spring MVC+MyBatis之零配置之路源代码"项目旨在展示如何在不使用XML配置的情况下,通过Java配置和注解驱动的方式来搭建一个完整的SSM(Spring、Spring MVC、MyBatis)应用。 Spring框架作为基础,提供...
在Java企业级应用开发领域,Spring、SpringMVC和MyBatis是三个不可或缺的重要组件,它们共同构建了一个强大的、灵活的和可扩展的应用框架。这篇文章将深入探讨这三个框架的核心概念、工作原理以及如何将它们整合在...
基于ssm(spring+spring mvc+mybatis+maven)高仿bilibili视频网站项目源码.zip 基于ssm(spring+spring mvc+mybatis+maven)高仿bilibili视频网站项目源码.zip 基于ssm(spring+spring mvc+mybatis+maven)高仿bilibili...
在SSM整合中,Spring作为容器管理着所有bean的生命周期,负责初始化、装配以及管理应用中的对象。通过XML配置或基于注解的配置,我们可以声明并注入需要的服务,例如数据访问对象(DAO)、业务服务接口及其实现等。 ...
本项目——"spring+spring mvc+mybatis+mysql+dubbo整合开发任务流程后台管理系统"提供了一个完整的解决方案,涵盖了前端到后端的关键技术栈。下面我们将深入探讨这些技术及其在系统中的作用。 **Spring框架**:...
SSM框架,即Spring、Spring MVC和MyBatis的组合,是Java开发中常见的Web应用程序架构。这个压缩包提供了一套完整的SSM整合所需的jar包,使得开发者可以快速搭建一个基于这三个框架的项目。下面将详细讲解每个组件的...
【源码+配置教程】Maven3+Spring4+Spring MVC+mybatis3整合实例是IT领域中一种常见的Web开发框架组合,这个压缩包提供了一套完整的应用实例,旨在帮助开发者快速理解和掌握这些技术的集成与应用。在这个项目中,...
4. 创建Spring配置文件,配置数据源、事务管理器、MyBatis的SqlSessionFactory等。 5. 集成Redis,配置Redis连接池,编写RedisTemplate或StringRedisTemplate的配置,实现数据缓存操作。 6. 编写Spring MVC的...