|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
你希望java的IDE整合。这个是没有必要的,重要的是你理解java有多深以及怎么组织你的代码,即使没有IDE,代码照样能够编译运行的。编程AspectOrientedProgramming(AOP),面向切面编程,是一个对照抢手的话题。AOP次要完成的目标是针对营业处置过程当中的切面举行提取,它所面临的是处置过程当中的某个步骤或阶段,以取得逻辑过程当中各部分之间低耦合性的断绝效果。好比我们最多见的就是日记纪录了,举个例子,我们如今供应一个服务查询先生信息的,可是我们但愿纪录有谁举行了这个查询。假如依照传统的OOP的完成的话,那我们完成了一个查询先生信息的服务接口(StudentInfoService)和实在现类(StudentInfoServiceImpl.java),同时为了要举行纪录的话,那我们在完成类(StudentInfoServiceImpl.java)中要增加实在现纪录的历程。如许的话,假设我们要完成的服务有多个呢?那就要在每一个完成的类都增加这些纪录历程。如许做的话就会有点烦琐,并且每一个完成类都与纪录服务日记的举动紧耦合,违背了面向对象的划定规矩。那末如何才干把纪录服务的举动与营业处置过程当中分别出来呢?看起来仿佛就是查询先生的服务本人在举行,可是面前日记纪录对这些举动举行纪录,可是查询先生的服务不晓得存在这些纪录历程,这就是我们要会商AOP的目标地点。AOP的编程,仿佛就是把我们在某个方面的功效提出来与一批对象举行断绝,如许与一批对象之间下降了耦合性,能够就某个功效举行编程。
我们间接从代码动手吧,要完成以上的方针,我们可使用一个静态代办署理类(Proxy),经由过程拦阻一个对象的举动并增加我们必要的功效来完成。Java中的java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口为我们完成静态代办署理类供应了一个计划,可是该计划针对的对象要完成某些接口;假如针对的目标是类的话,cglib为我们供应了别的一个完成计划。等下会申明二者的区分。
1、接口的完成计划:
1)起首编写我们的营业接口(StudentInfoService.java):
publicinterfaceStudentInfoService{
voidfindInfo(StringstudentName);
}
及实在现类(StudentInfoServiceImpl.java):
publicclassStudentInfoServiceImplimplementsStudentInfoService{
publicvoidfindInfo(Stringname){
System.out.println("你今朝输出的名字是:"+name);
}
}
2)如今我们必要一个日记功效,在findInfo举动之前实行并纪录其举动,那末我们就起首要拦阻该举动。在实践实行的过程当中用一个代办署理类来替我们完成。Java中为我们供应了完成静态代办署理类的计划:
1处置拦阻目标的类(MyHandler.java)
importorg.apache.log4j.Logger;
importjava.lang.reflect.InvocationHandler;
importjava.lang.reflect.Proxy;
importjava.lang.reflect.Method;
publicclassMyHandlerimplementsInvocationHandler{
privateObjectproxyObj;
privatestaticLoggerlog=Logger.getLogger(MyHandler.class);
publicObjectbind(Objectobj){
this.proxyObj=obj;
returnProxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);
}
publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{
Objectresult=null;
try{
//请在这里拔出代码,在办法前挪用
log.info("挪用log日记办法"+method.getName());
result=method.invoke(proxyObj,args);//原办法
//请在这里拔出代码,办法后挪用
}catch(Exceptione){
e.printStackTrace();
}
returnresult;
}
}
2我们完成一个工场,为了便利我们利用该拦阻类(AOPFactory.java):
publicclassAOPFactory{
privatestaticObjectgetClassInstance(StringclzName){
Objectobj=null;
try{
Classcls=Class.forName(clzName);
obj=(Object)cls.newInstance();
}catch(ClassNotFoundExceptioncnfe){
System.out.println("ClassNotFoundException:"+cnfe.getMessage());
}catch(Exceptione){
e.printStackTrace();
}
returnobj;
}
publicstaticObjectgetAOPProxyedObject(StringclzName){
Objectproxy=null;
MyHandlerhandler=newMyHandler();
Objectobj=getClassInstance(clzName);
if(obj!=null){
proxy=handler.bind(obj);
}else{
System.out.println("Cantgettheproxyobj");
//throw
}
returnproxy;
}
}
3)基础的拦阻与其工场我们都完成了,如今测试(ClientTest.java):
publicclassClientTest{
publicstaticvoidmain(String[]args){
StudentInfoServicestudentInfo=(StudentInfoService)AOPFactory.getAOPProxyedObject("StudentInfoServiceImpl");
studentInfo.findInfo("阿飞");
}
}
输入了局(看你的log4j设置):
[INFO]挪用log日记办法findInfo
你今朝输出的名字是:阿飞
如许我们必要的效果就出来了,营业处置本人在举行,可是我们完成了日记功效,而营业处置(StudentInfoService)基本不晓得存在该举动的。可是Java中供应的静态代办署理类的完成是针对完成了某些接口的类,假如没有完成接口的话,不克不及创立代办署理类,看以上部分:
returnProxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);
看到了没有?obj.getClass().getInterfaces()请求完成了某些接口。以下供应哪些没有完成接口的完成计划:
2、子类的完成计划。
起首,请上彀下CGLib的包,http://sourceforge.net/project/showfiles.php?group_id=56933。设置好classpath路径,CGLib与java尺度库供应的完成计划分歧,cglib次要是基于完成类(如StudentInfoServiceImpl.java)扩大一个子类来完成。与DynamicProxy中的Proxy和InvocationHandler绝对应,net.sf.cglib.proxy.Enhancer和MethodInterceptor在CGLib中卖力完成代办署理对象创立和办法截获处置,发生的是方针类的子类而不是经由过程接口来完成办法拦阻的,Enhancer次要是用于机关静态代办署理子类来完成拦阻,MethodInterceptor(扩大了Callback接口)次要用于完成aroundadvice(AOP中的观点):
1)我们的营业处置(StudentInfoServiceImpl.java):
publicclassStudentInfoServiceImpl{
publicvoidfindInfo(Stringname){
System.out.println("你今朝输出的名字是:"+name);
}
}
2)实施一个工具来处置日记功效(AOPInstrumenter.java):
importnet.sf.cglib.proxy.MethodInterceptor;
importnet.sf.cglib.proxy.Enhancer;
importnet.sf.cglib.proxy.MethodProxy;
importjava.lang.reflect.Method;
importorg.apache.log4j.Logger;
publicclassAOPInstrumenterimplementsMethodInterceptor{
privateLoggerlog=Logger.getLogger(AOPInstrumenter.class);
privateEnhancerenhancer=newEnhancer();
publicObjectgetInstrumentedClass(Classclz){
enhancer.setSuperclass(clz);
enhancer.setCallback(this);
returnenhancer.create();
}
publicObjectintercept(Objecto,Methodmethod,Object[]args,MethodProxyproxy)throwsThrowable{
log.info("挪用日记办法"+method.getName());
Objectresult=proxy.invokeSuper(o,args);
returnresult;
}
}
3)我们来测试一下(AOPTest.java):
publicclassAOPTest{
publicstaticvoidmain(String[]args){
AOPInstrumenterinstrumenter=newAOPInstrumenter();
StudentInfoServiceImplstudentInfo=(StudentInfoServiceImpl)instrumenter.getInstrumentedClass(StudentInfoServiceImpl.class);
studentInfo.findInfo("阿飞");
}
}
输入了局与以上不异。
CGLib中为完成以上目标,次要供应的类
1)Enhancer:setCallback(Callback),setSuperclass(Class),create()前往静态子类Object
2)MethodInterceptor必需完成的接口:intercept(Object,Method,Object[],MethodProxy)前往的是原办法挪用的了局。和Proxy道理一样。
3、以上的两个复杂完成AOP的计划都为你筹办好了,你能够本人编写测试一下,以下复杂先容一下AOP的基础观点:
1)aspect(切面):完成了cross-cutting功效,是针对切面的模块。最多见的是logging模块,如许,程序按功效被分为好几层,假如按传统的承继的话,贸易模子承继日记模块的话基本没有甚么意义,而经由过程创立一个logging切面就能够利用AOP来完成不异的功效了。
2)jointpoint(毗连点):毗连点是切面拔出使用程序的中央,该点能被办法挪用,并且也会被抛出不测。毗连点是使用程序供应给切面拔出的中央,能够增加新的办法。好比以上我们的切点能够以为是findInfo(String)办法。
3)advice(处置逻辑):advice是我们切面功效的完成,它关照程序新的举动。如在logging里,loggingadvice包含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对象的历程:complietime,classloadtime,runtime
我们AOP编程复杂进门就到此为止了,但愿这篇文章对列位读者有匡助,对这篇Blog有甚么倡议的话能够留言给我:gdanthrowwy@126.com
而学习JAVA我觉得最应该避免的就是:只学习,不思考,只记忆,不实践! |
|