`
heimuad
  • 浏览: 297558 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

AOP编程入门--Java篇zz

    博客分类:
  • Java
阅读更多
AOP编程入门--Java篇
Aspect Oriented Programming(AOP),面向切面编程,是一个比较热门的话题。AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。比如我们最常见的就是日志记录了,举个例子,我们现在提供一个服务查询学生信息的,但是我们希望记录有谁进行了这个查询。如果按照传统的OOP的实现的话,那我们实现了一个查询学生信息的服务接口(StudentInfoService)和其实现类(StudentInfoServiceImpl.java),同时为了要进行记录的话,那我们在实现类(StudentInfoServiceImpl.java)中要添加其实现记录的过程。这样的话,假如我们要实现的服务有多个呢?那就要在每个实现的类都添加这些记录过程。这样做的话就会有点繁琐,而且每个实现类都与记录服务日志的行为紧耦合,违反了面向对象的规则。那么怎样才能把记录服务的行为与业务处理过程中分离出来呢?看起来好像就是查询学生的服务自己在进行,但是背后日志记录对这些行为进行记录,但是查询学生的服务不知道存在这些记录过程,这就是我们要讨论AOP的目的所在。AOP的编程,好像就是把我们在某个方面的功能提出来与一批对象进行隔离,这样与一批对象之间降低了耦合性,可以就某个功能进行编程。
    我们直接从代码入手吧,要实现以上的目标,我们可以使用一个动态代理类(Proxy),通过拦截一个对象的行为并添加我们需要的功能来完成。Java中的java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口为我们实现动态代理类提供了一个方案,但是该方案针对的对象要实现某些接口;如果针对的目的是类的话,cglib为我们提供了另外一个实现方案。等下会说明两者的区别。
一、接口的实现方案:
1)首先编写我们的业务接口(StudentInfoService.java):
public interface StudentInfoService{
void findInfo(String studentName);
}
     及其实现类(StudentInfoServiceImpl.java):
public class StudentInfoServiceImpl implements StudentInfoService{
public void findInfo(String name){
  System.out.println("你目前输入的名字是:"+name);
}
}
2)现在我们需要一个日志功能,在findInfo行为之前执行并记录其行为,那么我们就首先要拦截该行为。在实际执行的过程中用一个代理类来替我们完成。Java中为我们提供了实现动态代理类的方案:
1处理拦截目的的类(MyHandler.java)
import org.apache.log4j.Logger;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.reflect.Method;

public class MyHandler implements InvocationHandler{
private Object proxyObj;
private static Logger log=Logger.getLogger(MyHandler.class);

public Object bind(Object obj){
  this.proxyObj=obj;
  return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);
}

public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
  Object result=null;
  try{
   //请在这里插入代码,在方法前调用
   log.info("调用log日志方法"+method.getName());
   result=method.invoke(proxyObj,args); //原方法
   //请在这里插入代码,方法后调用
  }catch(Exception e){
   e.printStackTrace();
  }
  return result;
}
}
2我们实现一个工厂,为了方便我们使用该拦截类(AOPFactory.java):
public class AOPFactory{
private static Object getClassInstance(String clzName){
  Object obj=null;
  try{
   Class cls=Class.forName(clzName);
   obj=(Object)cls.newInstance();
  }catch(ClassNotFoundException cnfe){
   System.out.println("ClassNotFoundException:"+cnfe.getMessage());
  }catch(Exception e){
   e.printStackTrace();
  }
  return obj;
}

public static Object getAOPProxyedObject(String clzName){
  Object proxy=null;
  MyHandler handler=new MyHandler();
  Object obj=getClassInstance(clzName);
  if(obj!=null) {
   proxy=handler.bind(obj);
  }else{
   System.out.println("Cant get the proxyobj");
   //throw
  }
  return proxy;
}
}

3)基本的拦截与其工厂我们都实现了,现在测试(ClientTest.java):
public class ClientTest{
public static void main(String[] args){
  StudentInfoService studentInfo=(StudentInfoService)AOPFactory.getAOPProxyedObject("StudentInfoServiceImpl");
  studentInfo.findInfo("阿飞");
}
}
输出结果(看你的log4j设置):
[INFO]调用log日志方法findInfo
你目前输入的名字是:阿飞
     这样我们需要的效果就出来了,业务处理自己在进行,但是我们实现了日志功能,而业务处理(StudentInfoService)根本不知道存在该行为的。但是Java中提供的动态代理类的实现是针对实现了某些接口的类,如果没有实现接口的话,不能创建代理类,看以上部分:
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);
看到了没有?obj.getClass().getInterfaces()要求实现了某些接口。以下提供哪些没有实现接口的实现方案:

二、子类的实现方案。
      首先,请上网下CGLib的包,http://sourceforge.net/project/showfiles.php?group_id=56933 。设置好classpath路径,CGLib与java标准库提供的实现方案不同,cglib主要是基于实现类(如StudentInfoServiceImpl.java)扩展一个子类来实现。与Dynamic Proxy中的Proxy和InvocationHandler相对应,net.sf.cglib.proxy.Enhancer和MethodInterceptor在CGLib中负责完成代理对象创建和方法截获处理,产生的是目标类的子类而不是通过接口来实现方法拦截的,Enhancer主要是用于构造动态代理子类来实现拦截,MethodInterceptor(扩展了Callback接口)主要用于实现around advice(AOP中的概念):
     1)我们的业务处理(StudentInfoServiceImpl.java):
public class StudentInfoServiceImpl{
public void findInfo(String name){
  System.out.println("你目前输入的名字是:"+name);
}
}
     2)实行一个工具来处理日志功能(AOPInstrumenter.java):
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
import org.apache.log4j.Logger;

public class AOPInstrumenter implements MethodInterceptor{
private Logger log=Logger.getLogger(AOPInstrumenter.class);
private Enhancer enhancer=new Enhancer();

public Object getInstrumentedClass(Class clz){
  enhancer.setSuperclass(clz);
  enhancer.setCallback(this);
  return enhancer.create();
}

public Object intercept(Object o,Method method,Object[] args,MethodProxy proxy) throws Throwable{
  log.info("调用日志方法"+method.getName());
  Object result=proxy.invokeSuper(o,args);
  return result;
}

}
     3)我们来测试一下(AOPTest.java):
public class AOPTest{
public static void main(String[] args){
  AOPInstrumenter instrumenter=new AOPInstrumenter();
  StudentInfoServiceImpl studentInfo=(StudentInfoServiceImpl)instrumenter.getInstrumentedClass(StudentInfoServiceImpl.class);
  studentInfo.findInfo("阿飞");
}
}
   输出结果与以上相同。
CGLib中为实现以上目的,主要提供的类
1)Enhancer:setCallback(Callback) ,setSuperclass(Class) ,create()返回动态子类Object
2)MethodInterceptor必须实现的接口:intercept(Object,Method,Object[],MethodProxy)返回的是原方法调用的结果。和Proxy原理一样。

三、以上的两个简单实现AOP的方案都为你准备好了,你可以自己编写测试一下,以下简单介绍一下AOP的基本概念:
1)aspect(切面):实现了cross-cutting功能,是针对切面的模块。最常见的是logging模块,这样,程序按功能被分为好几层,如果按传统的继承的话,商业模型继承日志模块的话根本没有什么意义,而通过创建一个logging切面就可以使用AOP来实现相同的功能了。
2)jointpoint(连接点):连接点是切面插入应用程序的地方,该点能被方法调用,而且也会被抛出意外。连接点是应用程序提供给切面插入的地方,可以添加新的方法。比如以上我们的切点可以认为是findInfo(String)方法。
3)advice(处理逻辑):advice是我们切面功能的实现,它通知程序新的行为。如在logging里,logging advice包括logging的实现代码,比如像写日志到一个文件中。advice在jointpoint处插入到应用程序中。以上我们在MyHandler.java中实现了advice的功能
4)pointcut(切点):pointcut可以控制你把哪些advice应用于jointpoint上去,通常你使用pointcuts通过正则表达式来把明显的名字和模式进行匹配应用。决定了那个jointpoint会获得通知。
5)introduction:允许添加新的方法和属性到类中。
6)target(目标类):是指那些将使用advice的类,一般是指独立的那些商务模型。比如以上的StudentInfoServiceImpl.

7)proxy(代理类):使用了proxy的模式。是指应用了advice的对象,看起来和target对象很相似。
8)weaving(插入):是指应用aspects到一个target对象创建proxy对象的过程:complie time,classload time,runtime
分享到:
评论

相关推荐

    Spring5 框架 ---- AOP ---- 代码

    Spring5 框架 ---- AOP ---- 代码 Spring5 框架 ---- AOP ---- 代码 Spring5 框架 ---- AOP ---- 代码 Spring5 框架 ---- AOP ---- 代码 Spring5 框架 ---- AOP ---- 代码 Spring5 框架 ---- AOP ---- 代码 Spring5 ...

    spring-aop-5.3.10-API文档-中文版.zip

    赠送jar包:spring-aop-5.3.10.jar; 赠送原API文档:spring-aop-5.3.10-javadoc.jar; 赠送源代码:spring-aop-5.3.10-sources.jar; 赠送Maven依赖信息文件:spring-aop-5.3.10.pom; 包含翻译后的API文档:spring...

    AOP入门------------------实例

    **AOP(面向切面编程)入门实例** AOP,全称为Aspect-Oriented Programming,是一种编程范式,旨在减少代码中的重复性,提高代码的模块化和可维护性。在Java开发中,AOP主要应用于日志记录、事务管理、性能监控等横...

    小马哥讲 Spring AOP 编程思想 - API 线索图.pdf

    在讨论Spring AOP(面向切面编程)时,首先需要理解几个核心概念。Spring AOP 是Spring框架提供的一个功能模块,它允许开发者将横切关注点(cross-cutting concerns)从业务逻辑中解耦出来,通过在方法调用前后进行...

    spring-aop-5.3.12-API文档-中英对照版.zip

    赠送jar包:spring-aop-5.3.12.jar; 赠送原API文档:spring-aop-5.3.12-javadoc.jar; 赠送源代码:spring-aop-5.3.12-sources.jar; 赠送Maven依赖信息文件:spring-aop-5.3.12.pom; 包含翻译后的API文档:spring...

    spring-aop-5.3.15-API文档-中文版.zip

    赠送jar包:spring-aop-5.3.15.jar; 赠送原API文档:spring-aop-5.3.15-javadoc.jar; 赠送源代码:spring-aop-5.3.15-sources.jar; 赠送Maven依赖信息文件:spring-aop-5.3.15.pom; 包含翻译后的API文档:spring...

    开发工具 aopalliance-1.0

    开发工具 aopalliance-1.0开发工具 aopalliance-1.0开发工具 aopalliance-1.0开发工具 aopalliance-1.0开发工具 aopalliance-1.0开发工具 aopalliance-1.0开发工具 aopalliance-1.0开发工具 aopalliance-1.0开发工具...

    spring-aop-5.3.15-API文档-中英对照版.zip

    赠送jar包:spring-aop-5.3.15.jar; 赠送原API文档:spring-aop-5.3.15-javadoc.jar; 赠送源代码:spring-aop-5.3.15-sources.jar; 赠送Maven依赖信息文件:spring-aop-5.3.15.pom; 包含翻译后的API文档:spring...

    spring-aop-5.3.7-API文档-中文版.zip

    赠送jar包:spring-aop-5.3.7.jar; 赠送原API文档:spring-aop-5.3.7-javadoc.jar; 赠送源代码:spring-aop-5.3.7-sources.jar; 赠送Maven依赖信息文件:spring-aop-5.3.7.pom; 包含翻译后的API文档:spring-aop...

    spring-aop-5.3.10-API文档-中英对照版.zip

    赠送jar包:spring-aop-5.3.10.jar;赠送原API文档:spring-aop-5.3.10-javadoc.jar;赠送源代码:spring-aop-5.3.10-sources.jar;赠送Maven依赖信息文件:spring-aop-5.3.10.pom;包含翻译后的API文档:spring-aop...

    spring-aop.jar各个版本

    spring-aop-1.1.1.jar spring-aop-1.2.6.jar spring-aop-1.2.9.jar spring-aop-2.0.2.jar spring-aop-2.0.6.jar spring-aop-2.0.7.jar spring-aop-2.0.8.jar spring-aop-2.0.jar spring-aop-2.5.1.jar spring-aop-...

    spring-aop-5.3.7-API文档-中英对照版.zip

    赠送jar包:spring-aop-5.3.7.jar; 赠送原API文档:spring-aop-5.3.7-javadoc.jar; 赠送源代码:spring-aop-5.3.7-sources.jar; 赠送Maven依赖信息文件:spring-aop-5.3.7.pom; 包含翻译后的API文档:spring-aop...

    aopalliance-repackaged-2.4.0-b34-API文档-中文版.zip

    标签:glassfish、external、repackaged、aopalliance、hk2、jar包、java、中文文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持...

    aopalliance-1.0.jar & aopalliance-1.0-src.jar

    在Java的面向切面编程(AOP)领域,AOP Alliance是一个至关重要的组件,尤其对于Spring框架的开发者来说,它是不可或缺的工具。aopalliance-1.0.jar是这个联盟的实现库,为不同AOP框架之间的互操作性提供了标准接口...

    aopalliance-1.0.jar下载

    在Java开发领域,面向切面编程(Aspect-Oriented Programming, AOP)是一种重要的编程范式,它旨在将关注点分离,使系统设计更为模块化,降低耦合度。而aopalliance-1.0.jar是实现这一目标的关键组件之一。这个库是...

    aop-mysql-demo

    【标题】"aop-mysql-demo" 是一个项目示例,它主要展示了如何在Java应用程序中结合使用面向切面编程(AOP)和MySQL数据库。这个项目可能旨在教学或者演示如何在实际开发中灵活地管理和切换不同的数据库,尤其是在多...

    aopalliance-repackaged-2.4.0-b34-API文档-中英对照版.zip

    标签:glassfish、external、repackaged、aopalliance、hk2、jar包、java、API文档、中英对照版; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和...

    开发工具 spring-aop-4.3.6.RELEASE

    开发工具 spring-aop-4.3.6.RELEASE开发工具 spring-aop-4.3.6.RELEASE开发工具 spring-aop-4.3.6.RELEASE开发工具 spring-aop-4.3.6.RELEASE开发工具 spring-aop-4.3.6.RELEASE开发工具 spring-aop-4.3.6.RELEASE...

    AOP编程入门

    ### AOP编程入门知识点详解 #### 一、AOP概念介绍 面向切面编程(Aspect-Oriented Programming,简称AOP)是一种编程范式,它旨在通过将横切关注点(cross-cutting concerns)从业务逻辑中解耦,提高系统的模块化...

    AOP编程入门 Word版

    【AOP编程入门详解】 面向切面编程(Aspect Oriented Programming,简称AOP)是一种编程范式,旨在解决传统面向对象编程(OOP)中的一些问题,如代码重复、高耦合度等。AOP的核心思想是将关注点分离,即把系统中...

Global site tag (gtag.js) - Google Analytics