Guice之前也是花了很少时间看一下,现在几乎忘了。再一看以前写的几篇关于guice的博客,写得一点都不到位,甚至有许多地方都没讲清楚,真是惭愧!现在突然又想关注一下IOC方面的东西,因此想好好看看,Guice到底能做些什么,能做到什么程度。有空也想看看其源码。看了一下源码才发现,其实源码只包含guice部分,而实际上guice实现了其它一些第三方的源码,至少包括三个组件的源码:
一、aopalliance.jar,此包就是aop联盟定义的一组关于AOP的公共接口。
二、cglib,反射使用目前公认的最好的cglib组件。
三、asm,由于cglib使用了asm组件,所以asm也很重要。
错误的估计了形式,也更加验证了guice的确是强大的,因此这些都是目前非常优秀的组件。关于AOP,了解不多,以前有想过学习aspectj的,但的确有点复杂,不太适合自己这种喜欢轻量级组件的要求,所以没有迈出那一步,关注guice时才发现,居然有AOP的功能,于是就花了点时间试一下,虽然功能并不是很完善,但使用起来也很简单,对于大多数要求并不复杂的应用来说,已经不错了。
由于guice2使用注解,所以看起来更简单,下面以验证用户为例,首先建一个注解:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ValidUser {
}
然后再建立一个拦截器:
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class ValidUserInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Object[] args = invocation.getArguments();
for (int i = 0; i < args.length; i++) {
System.out.println(args[i]);
}
return invocation.proceed();
}
}
注意上面的MethodInterceptor来自aopalliance包而不是cglib包。上面方法的作用是打印拦截方法的参数值。
要把拦截器与注解关联起来,而关联的动作是在Module中进行了的:
public class ValidUserModule extends AbstractModule {
@Override
protected void configure() {
bind(UserService.class).to(UserServiceImp.class);
bindInterceptor(Matchers.any(), Matchers.annotatedWith(ValidUser.class),
new ValidUserInterceptor());
}
}
上面绑定拦截器使用了bindInterceptor方法,需要注意的是匹配规则,上面使用了较简单的Matchers.any(),如果有一些其它的要求,可以选择使用not,only等方法,它们使得拦截器使用起来更加的灵活。
实例还用到两个辅助的类:
public interface UserService {
public void editUser(String username,String password);
}
public class UserServiceImp implements UserService{
@ValidUser
public void editUser(String username,String password){
System.out.println("UserService editUser");
}
}
测试类:
public class ValidUserTest {
@Test
public void validUser(){
Injector injector = Guice.createInjector(new ValidUserModule());
UserService us = injector.getInstance(UserService.class);
us.editUser("fans","java");
}
}
按照拦截器的要求,结果会打印相应的参数值。输出为:
引用
fans
java
UserService editUser
一个简单的拦截过程就这样实现了。不过要使用guice拦截器,有几个限制因素:
引用
* Classes must be public or package-private.
* Classes must be non-final
* Methods must be public, package-private or protected
* Methods must be non-final
* Instances must be created by Guice by an @Inject-annotated or no-argument constructor