【前面的话】

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 SandBox沙箱设计模式

    沙箱模式常见于YUI3 core,它是一种采用同一构造器(Constructor)生成彼此独立且互不干扰(self-contained)的实例对象,而从避免污染全局对象的方法. 命名空间 JavaSc ...

  2. mapper的前后缀

    1.<trim prefix="" suffix="" suffixOverrides="" prefixOverrides=&quo ...

  3. Java反射中method.isBridge() 桥接方法

    桥接方法是 JDK 1.5 引入泛型后,为了使Java的泛型方法生成的字节码和 1.5 版本前的字节码相兼容,由编译器自动生成的方法.我们可以通过Method.isBridge()方法来判断一个方法是 ...

  4. PHP日期时间操作

    一.设置时区 date_default_timezone_set('PRC'); 二.获取当前时间的 Unix 时间戳(格林威治时间 1970 年 1 月 1 日 00:00:00到当前时间的秒数)和 ...

  5. Maven-Optional Dependencies & Dependency Exclusion

    本文讨论可选依赖和排除依赖.  帮助用户理解它们是什么, 如何使用, 它们如何工作, 以及什么时候使用它们最合适. 本文也将解释为什么排除是基于单个依赖的, 而非POM级别的. Optional De ...

  6. log4net 性能测试

    1.执行事务:20260 次 写日志:        耗时11.59分 不写日志:    耗时11.55分 异步日志:    耗时12.49分 (个人电脑,.net 线程池调用线程写日志可能比主线程直 ...

  7. Jmeter-分布式

    转载自: http://www.51testing.com/html/28/116228-247521.html 由于Jmeter本身的瓶颈,当需要模拟数以千计的并发用户时,使用单台机器模拟所有的并发 ...

  8. Spring MVC 到 Spring Boot 的简化之路(山东数漫江湖)

    背景 从Servlet技术到Spring和Spring MVC,开发Web应用变得越来越简捷.但是Spring和Spring MVC的众多配置有时却让人望而却步,相信有过Spring MVC开发经验的 ...

  9. Frogs' Neighborhood(POJ1659+Havel-Hakimi定理)

    题目链接:http://poj.org/problem?id=1659 题目: 题意:根据他给你的每个点的度数构造一张无向图. 思路:自己WA了几发(好菜啊……)后看到discuss才知道这个要用Ha ...

  10. Different Integers(牛客多校第一场+莫队做法)

    题目链接:https://www.nowcoder.com/acm/contest/139/J 题目: 题意:给你n个数,q次查询,对于每次查询得l,r,求1~l和r~n元素得种类. 莫队思路:1.将 ...