Spring学习(二)——Spring中的AOP的初步理解
【前面的话】
Spring对我太重要了,做个关于web相关的项目都要使用Spring,每次去看Spring相关的知识,总是感觉一知半解,没有很好的系统去学习一下,现在抽点时间学习一下Spring。不知道为什么对Spring有一种莫名的喜欢感,也许是因为他的名字,有一种希望的感觉。
Spring学习过程中的总结和心得,本文介绍了初次学习Spring的时候,对于AOP的理解,希望后面有时间可以进行再进一步的学习,请选择性阅读。
本文由牲口TT在博客园首次发表,转载请保持文章的完整性并注明:
作者:牲口TT。
链接:http://www.cnblogs.com/xt0810/p/3596347.html
【相关文章】
【AOP介绍】
面向侧面的程序设计(aspect-oriented programming,AOP,又译作面向方面的程序设计、观点导向编程)是计算机科学中的一个术语,指一种程序设计范型。该范型以一种称为侧面(aspect,又译作方面)的语言构造为基础,侧面是一种新的模块化机制,用来描述分散在对象、类或函数中的横切关注点(crosscutting concern)。
侧面的概念源于对面向对象的程序设计的改进,但并不只限于此,它还可以用来改进传统的函数。与侧面相关的编程概念还包括元对象协议、主题(subject)、混入(mixin)和委托。
【面向切面】
一、 AOP要干什么?
依赖注入让相互协作的软件组件保持松散耦合,而AOP编程允许你把遍布应用各处的功能分离出来形成可重用的组件。
也就是说AOP把一些常用的服务进行模块化,并且用声明的方式将这些组件使用到其他业务组件中去。这样做的结果是:每一个业务组件只关心自己的业务逻辑,不用去了解一些常用服务组件。这样就保证了更高的内聚性。
二、 不使用AOP的麻烦?
由于系统会有很多不同的组件,每一个组件负责一块特定功能,我们希望每一个组件只关心它的自身核心功能,但是在系统中,会有一些组件比如:日志模块,事务管理和安全模块等这些组件会比较频繁的融入到其他核心业务逻辑组件中去,这些常用的组件会分散到其他多个组件中,这样带来的麻烦是:
- 如果这些常用的服务组件发生变化,那么我们需要在多个其他组件中进行修改。
- 这样使得我们的组件代码因为插入了与自身核心业务无关的服务性组件变得混乱。
三、 使用AOP的好处?
我的理解是:一个组件A,不关心其他常用的服务组件B,但是这个组件A使用组件B的时候,不是组件A自身去调用,而是通过配置等其他方式,比如Spring中可以通过xml配置文件。这样就使得A压根就不需要知道服务组件B是怎样的,爱存在不存在,爱怎么存在都与A无关。A只关心自己的业务逻辑,具体A使用B的时候,配置文件去做,与具体的A组件无关。
四、 情形一:不使用AOP思想的代码
我们继续使用上一篇文章中Person开Car的例子来进行说明。我们现在增加一个Assistant的类,这个就是一个助理,需要干的事情就是在我开车之前进行登记,在我开车回来的时候进行接待。
如果使用一般思想的编码,我们需要在Person类中调用Assistant类的两个方法,如下代码。但是这样做的问题是:
- 管理Assistant是不是Person类的职责,Assistant应该做他自己的分内的事情,压根不需要Person命令他,Person走的时候他进行登记,和回来的时候进行入库,这就是他的本职工作,不需要Person提醒。
- 同样,由于Person类需要使用Assistant,他就必须把Assistant注入到他的类中,这样就使得他的代码变得复杂了。并且如果有一个Person没有Assistant,那么我们应该怎么办?
1. Person.java
public class Person {
private Car car;
private Assistant assistant;
public Person(Car car,Assistant assistant){//构造器注入,传入的是car,也就是一个所有车型都必须实现的接口
this.car =car;//这里可以响应奥迪,宝马等任何一种车的实现。
this.assistant=assistant;
}//这里Person类没有与任何特定类型的车发生耦合,对于Person来说,任何一种特定的车,只需要实现Car接口即可。具体是哪一种车型,对Person来说无关紧要。
public void driver(){//从这里可以看出,如果没有使用AOP,也就是每个人都需要用一个助理,这样是不合理的。
assistant.BeforeDepart();//Person类使用Assistant的方法
car.GuaDang();
car.CaiYouMen();
car.DaFangXiang();
assistant.AfterBack();//Person类使用Assistant的方法
}
}
2. Assistant.java
public class Assistant {
public void BeforeDepart(){
System.out.println("您好,你今天开走了奥迪,我已经做了登记");
}
public void AfterBack(){
System.out.println("您回来了!请把车交给我,我自行入库就可以了");
}
}
3. Car.java
public interface Car {
public abstract void GuaDang();
public abstract void CaiYouMen();
public abstract void DaFangXiang();
}
4. AuDi.java
public class AuDi implements Car {
public void GuaDang(){
System.out.println("我是奥迪车,我在进行挂档");
}
public void CaiYouMen(){
System.out.println("我是奥迪车,我在进行踩油门");
}
public void DaFangXiang(){
System.out.println("我是奥迪车,我在进行打方向盘");
}
}
5. MainTest.java
public class MainTest {
public static void main(String[] args){
AuDi audi=new AuDi();
Assistant assistant=new Assistant();
Person boy =new Person(audi, assistant);
boy.driver();
}
}
6. 运行结果
您好,你今天开走了奥迪,我已经做了登记
我是奥迪车,我在进行挂档
我是奥迪车,我在进行踩油门
我是奥迪车,我在进行打方向盘
您回来了!请把车交给我,我自行入库就可以了
五、 情形二:使用AOP思想的代码
使用了AOP,Person类就不需要关心Assistant类,我们只需要声明Assistant需要做的事情,Person类就不在直接访问Assistant类的方法了。
本篇文章只是在理解AOP的思想,具体在Spring中AOP是怎么做?使用什么方法,以后在进行学习。
1. Person.java
public class Person {
private Car car;
public Person(){
}
public Person(Car car){//构造器注入,传入的是car,也就是一个所有车型都必须实现的接口
this.car =car;//这里可以响应奥迪,宝马等任何一种车的实现。
}//这里Person类没有与任何特定类型的车发生耦合,对于Person来说,任何一种特定的车,只需要实现Car接口即可。具体是哪一种车型,对Person来说无关紧要。
public void driver(){
car.GuaDang();
car.CaiYouMen();
car.DaFangXiang();
}
}
2. Assistant.java
public class Assistant {
public void BeforeDepart(){
System.out.println("您好,你今天开走了奥迪,我已经做了登记");
}
public void AfterBack(){
System.out.println("您回来了!请把车交给我,我自行入库就可以了");
}
}
3. Car.java
public interface Car {
public abstract void GuaDang();
public abstract void CaiYouMen();
public abstract void DaFangXiang();
}
4. AuDi.java
public class AuDi implements Car {
public void GuaDang(){
System.out.println("我是奥迪车,我在进行挂档");
}
public void CaiYouMen(){
System.out.println("我是奥迪车,我在进行踩油门");
}
public void DaFangXiang(){
System.out.println("我是奥迪车,我在进行打方向盘");
}
}
5. cartest.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<bean id="cartest" class="Person">
<constructor-arg ref="Car" />
</bean>
<bean id="Car" class="AuDi" />
<bean id="assistant" class="Assistant" />
<aop:config>
<aop:aspect ref="assistant">
<aop:pointcut id="ass" expression="execution(* driver(..))"/>
<aop:before pointcut-ref="ass" method="BeforeDepart"/>
<aop:after pointcut-ref="ass" method="AfterBack"/>
</aop:aspect>
</aop:config>
</beans>
6. MainTest.java
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainTest {
public static void main(String[] args){
ApplicationContext context = new ClassPathXmlApplicationContext("cartest.xml");
Person boy =(Person) context.getBean("cartest");
boy.driver();
}
}
7. 运行结果
您好,你今天开走了奥迪,我已经做了登记
我是奥迪车,我在进行挂档
我是奥迪车,我在进行踩油门
我是奥迪车,我在进行打方向盘
您回来了!请把车交给我,我自行入库就可以了
【注意问题】
在学习过程中,总是会遇到很多问题,而本文是自己学习过程中的总结,所以对于新手来说,遇到一个问题可能需要找半天的问题,所以下面写了一下新手可能会遇到的问题,以及需要注意的事项,选择性阅读。
一、 需要导入的jar包:
- asm.jar
- cglib-2.1.3.jar
- com.springsource.org.aopalliance-1.0.0.jar
- com.springsource.org.aspectj.tools-1.6.6.RELEASE.jar
- commons-logging-1.0.4.jar
- org.springframework.aop-3.0.1.RELEASE-A.jar
- org.springframework.asm-3.0.1.RELEASE-A.jar
- org.springframework.beans-3.0.2.RELEASE.jar
- org.springframework.context-3.0.2.RELEASE.jar
- org.springframework.core-3.0.2.RELEASE.jar
- org.springframework.expression-3.0.1.RELEASE-A.jar
二、 代码结构如下图:

红线部分代码属于同一个包中。
三、 可能遇到的错误:
1. 错误:
Caused by: java.lang.ClassNotFoundException:org.aopalliance.aop.Advice
解决办法:
导入:com.springsource.org.aopalliance-1.0.0.jar
2. 错误:
Caused by: org.springframework.aop.framework.AopConfigException: Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces.
解决办法:
导入:cglib-2.1.3.jar
3. 错误:
Caused by: java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
解决办法:
在Person类中加入一个默认构造函数,关于这个错误,下面的文章中有较为深入的描述。http://netfork.iteye.com/blog/286215
【参考资料】
1. 《Spring in action》 Craig Walls著 耿渊 张卫滨译
【后面的话】
有时感觉比较惶恐,有时有感觉比较安全,惶恐的时候就想着要好好学习。
——TT
Spring学习(二)——Spring中的AOP的初步理解的更多相关文章
- Spring学习(二)——Spring中的AOP的初步理解[转]
[前面的话] Spring对我太重要了,做个关于web相关的项目都要使用Spring,每次去看Spring相关的知识,总是感觉一知半解,没有很好的系统去学习一下,现在抽点时间学习一下Spring. ...
- Spring 学习笔记(六)—— AOP的简单理解
系统中的业务可以分为核心关注点和横切关注点. 核心关注点时业务处理的主要流程,而横切关注点是与核心业务无关但更为通用的业务. 各个横切关注点离散地穿插于核心业务之中,导致系统地每一个模块都与这些业务具 ...
- spring 学习(三):aop 学习
spring 学习(三):aop 学习 aop 概念 1 aop:面向切面(方面)编程,扩展功能不修改源代码实现 2 AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码 3 aop底层使用动态代 ...
- Spring基础(二)_面向切面(AOP)
面向切面编程 面向切面编程[AOP,Aspect Oriented Programming]:通过预编译方式和运行期间动态代理实现程序功能的统一维护的技术.AOP 是 Spring 框架中的一个重要内 ...
- Spring学习(十一)-----Spring使用@Required注解依赖检查
Spring学习(九)-----Spring依赖检查 bean 配置文件用于确定的特定类型(基本,集合或对象)的所有属性被设置.在大多数情况下,你只需要确保特定属性已经设置但不是所有属性.. 对于这种 ...
- Spring学习(六)-----Spring使用@Autowired注解自动装配
Spring使用@Autowired注解自动装配 在上一篇 Spring学习(三)-----Spring自动装配Beans示例中,它会匹配当前Spring容器任何bean的属性自动装配.在大多数情况下 ...
- spring学习(二) ———— AOP之AspectJ框架的使用
前面讲解了spring的特性之一,IOC(控制反转),因为有了IOC,所以我们都不需要自己new对象了,想要什么,spring就给什么.而今天要学习spring的第二个重点,AOP.一篇讲解不完,所以 ...
- Spring学习之Spring中AOP方式切入声明式事务
mybatis-spring官方文档说明 一个使用 MyBatis-Spring 的其中一个主要原因是它允许 MyBatis 参与到 Spring 的事务管理中.而不是给 MyBatis 创建一个新的 ...
- Spring学习4-面向切面(AOP)之Spring接口方式
一.初识AOP 关于AOP的学习可以参看帮助文档:spring-3.2.0.M2\docs\reference\html目录下index.html的相关章节 1.AOP:Aspect ...
随机推荐
- ExtJs在页面上window再调用Window的事件处理
今天在开发Ext的过程中遇到了一个恶心的问题,就是在ext.window页面,点击再次弹出window时,gridpanel中的store数据加载异常,不能正常被加载,会出现缓存,出现该问题,是因为w ...
- angularJS前端分页插件
首先在项目中引入 分页插件的 js 和 css: 在html页面引入 相关js 和 css: 在控制器中引入分页插件中定义的 module[可以打开pagination.js查看,可以看到 其实,在插 ...
- 清华大学计算机系大二 java 小学期考试题(摘自知乎)
public class Main { public void test(Object o) { System.out.println("Object"); } public vo ...
- spring cloud config的bootstrap.yml与application.proterties的区别
bootstrap.yml 和application.yml 都可以用来配置参数 bootstrap.yml可以理解成系统级别的一些参数配置,这些参数一般是不会变动的 application.ym ...
- liunx系统下安装mysql数据库5.7.13版本
一:在/usr/local目录下解压安装包
- CSS3知识之阴影box-shadow
一.定义和用法 box-shadow 属性向框添加一个或多个阴影. box-shadow: h-shadow v-shadow blur spread color inset; h-shadow ...
- Flume入门——Selector、Chanel等
1.selector (http://blog.csdn.net/looklook5/article/details/40430965) (http://blog.csdn.net/xiao_jun_ ...
- 【洛谷 P3194】 [HNOI2008]水平可见直线 (单调栈)
题目链接 把线段以斜率为第一关键字,截距为第二关键字升序排序. 然后维护一个单调栈,保证栈中两两线段的交点的\(x\)坐标单调上升就行了.栈中的线段即为所求. #include <cstdio& ...
- python keras YOLOv3实现目标检测
1.连接 https://www.jianshu.com/p/3943be47fe84
- Python第三方库matplotlib(2D绘图库)入门与进阶
Matplotlib 一 简介: 二 相关文档: 三 入门与进阶案例 1- 简单图形绘制 2- figure的简单使用 3- 设置坐标轴 4- 设置legend图例 5- 添加注解和绘制点以及在图形上 ...