【前面的话】

Spring对我太重要了,做个关于web相关的项目都要使用Spring,每次去看Spring相关的知识,总是感觉一知半解,没有很好的系统去学习一下,现在抽点时间学习一下Spring。不知道为什么对Spring有一种莫名的喜欢感,也许是因为他的名字,有一种希望的感觉。

Spring学习过程中的总结和心得,本文介绍了初次学习Spring的时候,对于AOP的理解,希望后面有时间可以进行再进一步的学习,请选择性阅读。

本文由牲口TT在博客园首次发表,转载请保持文章的完整性并注明:
作者:牲口TT
链接:http://www.cnblogs.com/xt0810/p/3596347.html

【相关文章】

Spring学习(一)——Spring中的依赖注入简介

AOP介绍】

面向侧面的程序设计(aspect-oriented programming,AOP,又译作面向方面的程序设计、观点导向编程)是计算机科学中的一个术语,指一种程序设计范型。该范型以一种称为侧面(aspect,又译作方面)的语言构造为基础,侧面是一种新的模块化机制,用来描述分散在对象、类或函数中的横切关注点(crosscutting concern)。

侧面的概念源于对面向对象的程序设计的改进,但并不只限于此,它还可以用来改进传统的函数。与侧面相关的编程概念还包括元对象协议、主题(subject)、混入(mixin)和委托。

【面向切面】

一、     AOP要干什么?

依赖注入让相互协作的软件组件保持松散耦合,而AOP编程允许你把遍布应用各处的功能分离出来形成可重用的组件。

也就是说AOP把一些常用的服务进行模块化,并且用声明的方式将这些组件使用到其他业务组件中去。这样做的结果是:每一个业务组件只关心自己的业务逻辑,不用去了解一些常用服务组件。这样就保证了更高的内聚性。

二、     不使用AOP的麻烦?

由于系统会有很多不同的组件,每一个组件负责一块特定功能,我们希望每一个组件只关心它的自身核心功能,但是在系统中,会有一些组件比如:日志模块,事务管理和安全模块等这些组件会比较频繁的融入到其他核心业务逻辑组件中去,这些常用的组件会分散到其他多个组件中,这样带来的麻烦是:

  1. 如果这些常用的服务组件发生变化,那么我们需要在多个其他组件中进行修改。
  2. 这样使得我们的组件代码因为插入了与自身核心业务无关的服务性组件变得混乱。

三、     使用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包:

  1. asm.jar
  2. cglib-2.1.3.jar
  3. com.springsource.org.aopalliance-1.0.0.jar
  4. com.springsource.org.aspectj.tools-1.6.6.RELEASE.jar
  5. commons-logging-1.0.4.jar
  6. org.springframework.aop-3.0.1.RELEASE-A.jar
  7. org.springframework.asm-3.0.1.RELEASE-A.jar
  8. org.springframework.beans-3.0.2.RELEASE.jar
  9. org.springframework.context-3.0.2.RELEASE.jar
  10. org.springframework.core-3.0.2.RELEASE.jar
  11. 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的初步理解的更多相关文章

  1. Spring学习(二)——Spring中的AOP的初步理解[转]

      [前面的话] Spring对我太重要了,做个关于web相关的项目都要使用Spring,每次去看Spring相关的知识,总是感觉一知半解,没有很好的系统去学习一下,现在抽点时间学习一下Spring. ...

  2. Spring 学习笔记(六)—— AOP的简单理解

    系统中的业务可以分为核心关注点和横切关注点. 核心关注点时业务处理的主要流程,而横切关注点是与核心业务无关但更为通用的业务. 各个横切关注点离散地穿插于核心业务之中,导致系统地每一个模块都与这些业务具 ...

  3. spring 学习(三):aop 学习

    spring 学习(三):aop 学习 aop 概念 1 aop:面向切面(方面)编程,扩展功能不修改源代码实现 2 AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码 3 aop底层使用动态代 ...

  4. Spring基础(二)_面向切面(AOP)

    面向切面编程 面向切面编程[AOP,Aspect Oriented Programming]:通过预编译方式和运行期间动态代理实现程序功能的统一维护的技术.AOP 是 Spring 框架中的一个重要内 ...

  5. Spring学习(十一)-----Spring使用@Required注解依赖检查

    Spring学习(九)-----Spring依赖检查 bean 配置文件用于确定的特定类型(基本,集合或对象)的所有属性被设置.在大多数情况下,你只需要确保特定属性已经设置但不是所有属性.. 对于这种 ...

  6. Spring学习(六)-----Spring使用@Autowired注解自动装配

    Spring使用@Autowired注解自动装配 在上一篇 Spring学习(三)-----Spring自动装配Beans示例中,它会匹配当前Spring容器任何bean的属性自动装配.在大多数情况下 ...

  7. spring学习(二) ———— AOP之AspectJ框架的使用

    前面讲解了spring的特性之一,IOC(控制反转),因为有了IOC,所以我们都不需要自己new对象了,想要什么,spring就给什么.而今天要学习spring的第二个重点,AOP.一篇讲解不完,所以 ...

  8. Spring学习之Spring中AOP方式切入声明式事务

    mybatis-spring官方文档说明 一个使用 MyBatis-Spring 的其中一个主要原因是它允许 MyBatis 参与到 Spring 的事务管理中.而不是给 MyBatis 创建一个新的 ...

  9. Spring学习4-面向切面(AOP)之Spring接口方式

    一.初识AOP    关于AOP的学习可以参看帮助文档:spring-3.2.0.M2\docs\reference\html目录下index.html的相关章节       1.AOP:Aspect ...

随机推荐

  1. Javascript计算世界完全对称日

    今天是 2011-11-02 日,微博啊.G+啊什么的都传是世界完全对称日,还说是多少年一遇的.下面写个 JavaScript 小程序,看看是否真的N年一遇.计算范围在公元2000年到3000年. 名 ...

  2. mybatis生成的pojo 中的属性或方法不够我们当做dto使用时

    我们在写代码的时候,如果一个 mybatis生成的pojo 中的属性或方法不够我们使用(当做dto和前台交互)时,我们有两种方法: 第一: 直接在 原 pojo 中增加属性或者方法 第二:我们可以再写 ...

  3. HDU 2094 拓扑排序

    产生冠军 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

  4. 题解【luogu1073 最优贸易】

    Solution 考虑原图是 DAG 时怎么做. 拓扑排序 + dp ,令 dp[i] 表示 \(1\) 到 \(i\) 的路径上最小的卖出价格.转移方程就是对每一个可以到达这个点的 dp 取个 mi ...

  5. ACM2647拓扑排序逆运算

    2647题是对工人排序问题,不是从头到尾排序,而是从尾到头排序: 代码中用到vector和queue容器,权当练习. 用广搜进行拓扑排序的逆运算. #include<iostream> # ...

  6. [LeetCode] 5. Longest Palindromic Substring ☆☆☆☆

    Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...

  7. Maven -- 在进行war打包时用正式环境的配置覆盖开发环境的配置

    我们的配置文件一般都放在  src/main/resource 目录下. 假定我们的正式环境配置放在 src/main/online-resource 目录下. 那么打成war包时,我们希望用onli ...

  8. 插入排序Insertion sort 2

    原理类似桶排序,这里总是需要10个桶,多次使用 首先以个位数的值进行装桶,即个位数为1则放入1号桶,为9则放入9号桶,暂时忽视十位数 例如 待排序数组[62,14,59,88,16]简单点五个数字 分 ...

  9. 知问前端——cookie插件

    Cookie是网站用来在客户端保存识别用户的一种小文件.一般可以保存用户登录信息.购物数据信息等一系列微小信息. 一.使用cookie插件 官方网站:http://plugins.jquery.com ...

  10. javascript 访问cookie信息

    在Javascript脚本里,一个cookie 实际就是一个字符串属性.当你读取cookie的值时,就得到一个字符串,里面当前WEB页使用的所有cookies的名称和值.每个cookie除了 name ...