活用Srping AOP

活用Srping AOP

总有那么一些代码,在测试环境下,是不能轻易被调用的。
比如:
1)发送系统任务邮件到客户邮箱,可能一不小心,就把测试邮件发送给了真实客户的邮箱里;
2)调用跨公司的系统接口,而对方系统没有测试环境,每调用一次接口,就会在对方系统产生垃圾数据;
3)调用的代码可能需要大量的cpu运算,占用大量的内存空间,消耗大量的资源;
等等。。。

为了解决这样的需求,
1)在代码中,到处充斥着这样的代码:
1  if (在测试环境下) {
2      打印日志;
3  else  {
4      调用真实的业务逻辑;
5  }
于是乎,需要到处维护这样的代码,一旦增加此类需求,就需要编写同样的代码

2)部分懒惰的程序员,连这样的if...else...也不愿意写,仅仅在注释中说明下在测试环境中调用方法的危害性。
于是,在测试阶段,一旦和测试部门沟通不足,导致代码还是经常被调用到,如果是在作压力,性能测试,那么危害性可想而已。
曾发生过,压力测试某个功能,结果把大量的测试邮件,发送给了客户,影响很差。


那么,如何解决这样的需求场景呢?
没错,采用proxy模式,可以搞定。考虑到现在很多企业都使用Spring作为IOC容器,本文就简单介绍,如何采用spring aop来解决问题。

以发送邮件的需求作为虚拟场景。
现在有个Service,专门负责邮件的发送。
1. MyService.java
1  public   class  MyService {
2       public   void  sendMailSafely() {
3      System.out.println( " send mail successfully. " );
4      }
5  }

如果这个sendMailSafely被客户端调用,那么毫无疑问,邮件不管任何环境下,都会被成功发送。
需要有个方法拦截器,对这个方法做拦截。
2. MyInterceptor.java
 1  public   class  MyInterceptor  implements  MethodInterceptor {
 2 
 3       private   boolean  isProduction  =   false ;
 4 
 5      @Override
 6       public  Object invoke(MethodInvocation invocation)  throws  Throwable {
 7       if  ( ! isProduction) {
 8          System.out.println( " is production environment.do nothing " );
 9           return   null ;
10      }
11       return  invocation.proceed();
12      }
13 
14       public   void  setProduction( boolean  isProduction) {
15       this .isProduction  =  isProduction;
16      }
17 
18  }
这个拦截器,根据配置文件的参数isProduction判断是否在正式环境,如果是在测试环境,对方法做拦截,仅仅打印log,不真实调用业务逻辑。

如何让sendMailSafely()方法被此拦截器做拦截,所以通过spring配置文件,配置一个advisor,通知对以Safely结尾的方法做拦截
3.  application.xml
 1  < bean  id ="safetyAdvisor"  class ="org.springframework.aop.support.RegexpMethodPointcutAdvisor"  scope ="singleton" >
 2       < property  name ="advice" >
 3         < ref  local ="myInterceptor"   />
 4       </ property >
 5       < property  name ="patterns" >
 6         < list >
 7           < value > .*Safely </ value >
 8         </ list >
 9       </ property >
10     </ bean >

附上application.xml的全部内容
 1  < beans  default-autowire ="byName" >
 2 
 3     <!--  service实例  -->
 4     < bean  id ="myService"  class ="cn.zeroall.javalab.aop.MyService"  scope ="singleton"   />
 5 
 6     <!--  方法拦截器  -->
 7     < bean  id ="myInterceptor"  class ="cn.zeroall.javalab.aop.MyInterceptor"  scope ="singleton" >
 8       < property  name ="production"  value ="false"   />
 9     </ bean >
10 
11     <!--  通知者  -->
12     < bean  id ="safetyAdvisor"  class ="org.springframework.aop.support.RegexpMethodPointcutAdvisor"  scope ="singleton" >
13       < property  name ="advice" >
14         < ref  local ="myInterceptor"   />
15       </ property >
16       < property  name ="patterns" >
17         < list >
18           < value > .*Safely </ value >
19         </ list >
20       </ property >
21     </ bean >
22 
23     <!--  myService代理类  -->
24     < bean  id ="safetyService"  class ="org.springframework.aop.framework.ProxyFactoryBean"  scope ="singleton" >
25       < property  name ="interceptorNames" >
26         < list >
27           < value > safetyAdvisor </ value >
28         </ list >
29       </ property >
30       < property  name ="targetName"  value ="myService"   />
31     </ bean >
32 
33  </ beans >


写一个Client类来做演示。
4. Client.java
 1  public   class  Client {
 2 
 3       private  ApplicationContext ctx  =   new  ClassPathXmlApplicationContext(
 4           " cn/zeroall/javalab/aop/application.xml " );;
 5 
 6       public   static   void  main(String[] args) {
 7          Client c  =   new  Client();
 8          c.sendMail();
 9          c.sendMailSafety();
10      }
11 
12       public   void  sendMail() {
13          MyService myService  =  (MyService) ctx.getBean( " myService " );
14          myService.sendMailSafely();
15      }
16 
17       public   void  sendMailSafety() {
18          MyService myService  =  (MyService) ctx.getBean( " safetyService " );
19          myService.sendMailSafely();
20      }
21 
22  }
大家可以看看最终输出的结果内容。

一直来,我都不会滥用AOP,尤其反感使用AOP来写业务逻辑内容,但是对于这类非业务逻辑需求,采用spring aop技术那是刚刚好啊。

最后,附上全部代码文件(使用maven构建)。
演示代码

你可能感兴趣的:(活用Srping AOP)