google(轻量级依赖注入框架)Guice学习 (三) 作用域、AOP


一、作用域(控制对象生命周期)

利用上文业务,插入一个缓存类来说明作用域

/**
 * 实现cache,使用谷歌类库
 * 
 * @author lg
 *
 */
public class GuiceDemoCache extends AbstractCache<String, String> {

	private final Map<String, String> keyValues = new HashMap<>();

	@Override
	public String getIfPresent(Object key) {
		return keyValues.get(key);
	}

	@Override
	public void put(String key, String value) {
		keyValues.put(key, value);
	}
	
}

paymentServiceImpl部分代码:

public class PaymentServiceImpl implements PaymentService {
	private final Cache<String, String> cache;

	@Inject
	private PaymentServiceImpl(Cache<String, String> cache) {
		this.cache = cache;
	}

	void putCache(String key, String value) {//同一个包下可用    
		cache.put(key, value);
	}

PriceServiceImpl部分代码

private PrinceServiceImpl implements PrinceService{	
private final Cache<String,String> cache;
	@Inject
	public PriceServiceImpl(Set<String> supportedCurrenties,
			Cache<String,String> cache) {
		this.supportedCurrenties = supportedCurrenties;
		this.cache = cache;
	}

	String getCache(String key) {
		return cache.getIfPresent(key);// 如果存在获取
	}

测试类:

public class CacheTests {
	//由于没有实现接口,是写于类内部,故注入实现类
	@Inject private PaymentServiceImpl paymentServiceImpl; 
	@Inject private PriceServiceImpl priceServiceImpl; 
	
	@Before public void setUp() {
		Guice.createInjector(new ServerModule())
		.injectMembers(this);
		
	}
	
	@Test
	public void test() {
		paymentServiceImpl.putCache("Test","hahah");
		String cache = priceServiceImpl.getCache("Test");
		Assert.assertEquals(cache, "hahah");
	}

}

得出的结果是,他们的作用域仅局限于其方法内,每次获取仍需获取新的cache。

(一)单例(Singleton)

要使其全局唯一,

(1)@Singleton注解,javax.inject.Singleton;下;

(2)bind(new TypeLiteral<Cache<String,String>>(){})
.to(GuiceDemoCache.class).in(Singleton.class);;

(3)@Provides @Singleton Cache<String,String> getCache(){
return new GuiceDemoCache();
}

但是对于多线程而言,这样的单例并不能满足我们需要,因为缓存用的是HashMap,改成ConcurrentHashMap即可;


二、AOP

AOP: Aspect Oriented Programming 

Aspect:    一般针对日志,安全(全局拦截)、Transaction.....

        Guice有一个Methodinterceptor 接口:

            将方法拦截下来,来做Aspect所要做的事情,拦截下来后:

                (1)可以获得各种信息;    函数调用类、方法、参数。。。。

                (2)控制是否函数调用;    比如是否拥有权限访问。。。

                    eg:

                    OrderServerImpl.class中定义一个注解,仅需运行时即可

	@Override 	@Logged
	public void sendToPayment(long orderId) {
		long price = priceService.getPrice(orderId);
		paymentService.pay(orderId, price, sessionManager.getSessionId());
		ordersPaid = ordersPaid + 1;
		throw new RuntimeException("Price" + price
				+ ".SessionId=" + sessionManager.getSessionId()
				+ ".orderPaid=" + ordersPaid);
	}

                ServerModule.class

		bindInterceptor(Matchers.any(), //所有类别
				Matchers.annotatedWith(Logged.class),//注释为Logged的方法
				new MethodInterceptor() {//拦截处理
					
					@Override
					public Object invoke(MethodInvocation invocation) throws Throwable {
						Method method = invocation.getMethod();
						System.out.println(String.format("calling %s#%s(%s)",
								method.getDeclaringClass().getName(),
								method.getName(),
								Joiner.on(",").join(
										invocation.getArguments())));
						return invocation.proceed();
					}
				});


调用测试类:

calling CoffeeAndIce.GuiceDemo.server.impl.OrderServerImpl#sendToPayment(789)  //日志打印成功

tips:    requestInjection(instance);//可以用来要求注入某个类

总结流程:

    1、绑定Methodinterceptor 

    2、实现Methodinterceptor 

    3、在Methodinterceptor 中注入Dependency

warm:但是guice的Aop必须使用在通过guice创建的对象上,比如我们手工创建一个对象,添加日志AOP,这时,guice也是没有办法去拦截的,必须通过guice从头开始inject开始的才可以进行AOP处理

猜你喜欢

转载自blog.csdn.net/coffeeandice/article/details/80314301