ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Google Guice之AOP

2021-03-25 13:01:09  阅读:212  来源: 互联网

标签:拦截器 Guice class Google AOP 拦截 方法 public


为增强依赖注入功能,Guice支持方法拦截器。通过这个特性可以让方法在每次执行前调用一个匹配的方法。这适用于横切性关注点(切面),例如事务控制,权限与日志记录等。因为拦截器将一个问题分割成切面而不是对象;所以拦截器使用又被称为面向切面编程(AOP)。

大多数开发者不会直接编写方法拦截器,但是可能在一些类库中见到,需要进方法进行选择,创建一个拦截器并将它配置在Module中。

Matcher是一个简单接口,接收或者拒绝一个值。在Guice AOP中,我们需要两种Matcher,一是定义哪些类需要进行拦截;二是这些类的哪些方法需要进行拦截。为简化Matcher的创建,Guice使了工厂类(Matchers)来满足常见操作。

在需要拦截的方法被执行前,方法拦截器(MethodInterceptors)先被执行。拦截器可以检查该调用,包括方法本身,方法参数等。拦截器可以执行行横切性逻辑并且可以委托于底层方法。最后检查返回值,或者直接抛出异常。因为拦截器可能应用于非常多的方法并且被执行多次,所以其实现应该是高效的,非侵入式的。

例如:我们要实现在周末禁止方法调用,步骤如下:

  1. 编写一注解

    @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD)//标注于方法上
    @interface NotOnWeekends {}
  2. 将注解标注于要拦截的方法上

    public class RealBillingService implements BillingService {
    
     @NotOnWeekends
     public Receipt chargeOrder(PizzaOrder order, CreditCard creditCard) {
       ...
     }
    }
  3. 定义一个org.aopalliance.intercept.MethodInterceptor接口实现类,如果要执行底层方法,则执行invocation.proceed()方法(这一点与Spring中是一致的)

    public class WeekendBlocker implements MethodInterceptor {
     public Object invoke(MethodInvocation invocation) throws Throwable {
       Calendar today = new GregorianCalendar();
       if (today.getDisplayName(DAY_OF_WEEK, LONG, ENGLISH).startsWith("S")) {
         throw new IllegalStateException(
             invocation.getMethod().getName() + " not allowed on weekends!");
       }
       return invocation.proceed();
     }
    }
  4. 将拦截器配置于Module中,还需要定义哪些类哪些方法要被拦截。在如下例子中所有有都将会拦截,但是方法要有@NotOnWeekends注解才会被拦截

    public class NotOnWeekendsModule extends AbstractModule {
     protected void configure() {
       bindInterceptor(Matchers.any(), Matchers.annotatedWith(NotOnWeekends.class), 
           new WeekendBlocker());
     }
    }

在Guice AOP中,方法的拦截是在运行时动态生成字节码来实现的,Guice动态地创建被拦截类的一个子类,覆盖掉被拦截的方法并应用上拦截器。这其实就是动态代理模式的应用了。类中方法要能被拦截有如下限制:

  1. 类必须是public或者package-private
  2. 类不能是final类,因为是final类就不能创建其子类
  3. 方法必须是publicpackage-privateproctected
  4. 方法不能是final的,因为是final方法就无法被覆盖
  5. 只有Guice通过@Inject注解或者无参构造方法创建的实例的方法才能被拦截

对拦截器进行注入:

如果需要对拦截器注入依赖的话,需要使用requestInject方法:

public class NotOnWeekendsModule extends AbstractModule {
  protected void configure() {
    WeekendBlocker weekendBlocker = new WeekendBlocker();
    requestInjection(weekendBlocker);
    bindInterceptor(Matchers.any(), Matchers.annotatedWith(NotOnWeekends.class), 
       weekendBlocker);
  }
}

还有一个方法是使用Provider,然后将Provider作为拦截器构造方法参数传入,而且Provider中的依赖会自动注入:

public class NotOnWeekendsModule extends AbstractModule {
  protected void configure() {
    bindInterceptor(any(),
                    annotatedWith(NotOnWeekends.class),
                    new WeekendBlocker(getProvider(Calendar.class)));
  }
}

在使用拦截器的时候,如果拦截器调用了一个被该拦截器拦截的方法就进入死循环,其结果当然就是StackOverflowExeption
-------------------------------- END -------------------------------

及时获取更多精彩文章,请关注公众号《Java精讲》。

标签:拦截器,Guice,class,Google,AOP,拦截,方法,public
来源: https://blog.51cto.com/xtayfjpk/2671726

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有