首页 > 代码库 > Google Guice之AOP
Google Guice之AOP
为增强依赖注入功能,Guice支持方法拦截器。通过这个特性可以让方法在每次执行前调用一个匹配(过滤)方法。这适用于横切性关注点(切面),例如事务控制,权限与日志记录等。因为拦截器将一个问题分割成切面而不是对象;所以拦截器使用又被称为面向切面编程(AOP)。
大多数开发者不会直接编写方法拦截器,但是可能在一些类库中见到,需要进方法进行选择,创建一个拦截器并将它配置在Module中;例如Warp Persist。
Matcher是一个简单接口,接收或者拒绝一个值。在Guice AOP中,我们需要两中Matcher,一是定义哪些类需要进行拦截;二是这些类的哪些方法需要进行拦截。为简化Matcher的创建,Guice使了工厂类(Matchers)来满足这个常见操作。
在需要拦截的方法被执行前,方法拦截器(MethodInterceptors)先被执行。拦截器可以检查该调用,包括方法本身,方法参数等。拦截器可以执行行横切性逻辑并且可以委托于底层方法。最后检查返回值,或者直接抛出异常。因为拦截器可能应用于非常多的方法并且被执行多次,所以其实现应该是高效的,非侵入式的。
示例:在周末禁止方法调用。
2.将注解标注于要拦截的方法上
3.定义一org.aopalliance.intercept.MethodInterceptor接口实现类,如果要执行底层方法,则执行invocation.proceed()方法(这一点与Spring中是一致的)
4.将拦截器配置于Module中,还需要定义哪些类哪些方法要被拦截。在如下例子中所有有都将会拦截,但是方法要有@NotOnWeekends注解才会被拦截
Guice AOP限制:
在Guice AOP中,方法的拦截是在运行时动态生成字节码来实现的,Guice动态地创建被拦截类的一个子类,覆盖掉被拦截的方法并应用上拦截器。
这其实就是动态代理模式的应用了。类中方法要能被拦截有如下限制:
a.类必须是public或者package-private
b.类不能是final类,因为是final类就不能创建其子类
c.方法必须是public或package-private或proctected
d.方法不能是final的,因为是final方法就无法被覆盖
e.只有Guice通过@Inject注解或者无参构造方法创建的实例的方法才能被拦截
对拦截器进行注入:
如果需要对拦截器注入依赖的话,需要使用requestInject方法:
还有一个方法是使用Provider,然后将Provider作为拦截器构造方法参数传入,而且Provider中的依赖会自动注入:
在使用拦截器的时候,如果拦截器调用了一个被该拦截器拦截的方法就会限制方法循环调用死循环,其结果当然就是StackOverflowExeption。
大多数开发者不会直接编写方法拦截器,但是可能在一些类库中见到,需要进方法进行选择,创建一个拦截器并将它配置在Module中;例如Warp Persist。
<span style="font-size:14px;">@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD)//标注于方法上 @interface NotOnWeekends {}</span>
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 AOP中,方法的拦截是在运行时动态生成字节码来实现的,Guice动态地创建被拦截类的一个子类,覆盖掉被拦截的方法并应用上拦截器。
这其实就是动态代理模式的应用了。类中方法要能被拦截有如下限制:
a.类必须是public或者package-private
b.类不能是final类,因为是final类就不能创建其子类
c.方法必须是public或package-private或proctected
d.方法不能是final的,因为是final方法就无法被覆盖
e.只有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。
Google Guice之AOP
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。