设计:
1. 定义一个接口
2. 定义一个实现类
3. 定义一个Annotation
4. 定义一个Annotation解析器
5. 定义一个Proxy
6. 定义一个proxy来代理接口实现。
代码如下:
实现类
Annotation类
Annotation解析类
代理类
代理接口实现类
配置如下:
测试代码如下:
可以看到配置了Ehcache的方法实现了缓存功能。
1. 定义一个接口
2. 定义一个实现类
3. 定义一个Annotation
4. 定义一个Annotation解析器
5. 定义一个Proxy
6. 定义一个proxy来代理接口实现。
代码如下:
package org.frame.base.annotation.intercept;
public interface TestI {
public int add(int a,int b);
public int xx(int a);
}
实现类
public class Test implements TestI{
public int add(int a,int b){
return a+b;
}
@EhCache(key="cacheKey")
public int xx(int a){
return a;
}
}
Annotation类
package org.frame.base.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation indicating that a method (or all the methods on a class) can be cached.
*
* <p>The method arguments and signature are used for computing the key while the
* returned instance is used as the cache value.
*
* @author xxx
* @since 1.0
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface EhCache {
/**
* Name of the caches in which the update takes place.
* <p>May be used to determine the target cache (or caches), matching the
* qualifier value (or the bean name(s)) of (a) specific bean definition.
*/
String[] value() default "";
/**
* Spring Expression Language (SpEL) attribute for computing the key dynamically.
* <p>Default is "", meaning all method parameters are considered as a key.
*/
String key() default "";
/**
* Spring Expression Language (SpEL) attribute used for conditioning the method caching.
* <p>Default is "", meaning the method is always cached.
*/
String condition() default "";
}
Annotation解析类
package org.frame.base.annotation;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import org.springframework.util.Assert;
/**
* EhCache的操作对象
*
*
*/
public class EhCacheOperator {
private String name;
private Set<String> cacheNames = Collections.emptySet();//value
private String key = "";//key
private String condition = "";//condition
public Set<String> getCacheNames() {
return cacheNames;
}
public void setCacheNames(String[] cacheNames) {
Assert.notEmpty(cacheNames);
this.cacheNames = new LinkedHashSet<String>(cacheNames.length);
for (String string : cacheNames) {
this.cacheNames.add(string);
}
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getCondition() {
return condition;
}
public void setCondition(String condition) {
this.condition = condition;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
代理类
package org.frame.base.annotation.intercept;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Collection;
import org.frame.base.annotation.CachePaserImpl;
import org.frame.base.annotation.EhCacheOperator;
import org.frame.base.annotation.support.EhCacheAnnotationParser;
import org.frame.base.cache.LocalCacheManager;
/**
* 在代理层使用缓存
*
*/
public class ProxyHandler implements InvocationHandler {
EhCacheAnnotationParser ehcacheParser = new EhCacheAnnotationParser();
LocalCacheManager cacheManager = LocalCacheManager.getInstance();
private Object target;
public void setTarget(Object o){
this.target = o;
}
public ProxyHandler(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = null;
Collection<EhCacheOperator> ehcacheOperators = ehcacheParser.getCacheOperations(method, target.getClass());
if(ehcacheOperators == null || ehcacheOperators.isEmpty()){
result = method.invoke(target, args);
}else{
for(EhCacheOperator ehcacheOperator:ehcacheOperators ){
if(ehcacheOperator.getName().equals(CachePaserImpl.EHCACHE)){//ehcache 注解
Object cacheObj = cacheManager.get(ehcacheOperator.getKey());
if(cacheObj == null){
result = method.invoke(target, args);
if(result != null){
cacheManager.put(ehcacheOperator.getKey(), result);
}
}else{
result = cacheObj;
}
}
}
}
return result;
}
}
代理接口实现类
package org.frame.base.annotation.support;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import org.frame.base.annotation.intercept.ProxyHandler;
import org.springframework.beans.factory.FactoryBean;
/**
* 代理某个对象的所有接口
*
*/
public class EhCacheFactoryBean implements FactoryBean{
private Object target;
private Object proxyObj = null;
private Class<?>[] interfaceClass = null;
public void setTarget(Object target){
this.target = target;
}
/**
* 接口反映返回对象
* 1. serviceInterface 接口
* 2. target 目标地址,IP:端口
* @throws Exception
*/
public void init() throws Exception {
interfaceClass = target.getClass().getInterfaces();
InvocationHandler handler = new ProxyHandler(target);
proxyObj = Proxy.newProxyInstance(target.getClass().getClassLoader(),
interfaceClass, handler);
}
@Override
public Object getObject() throws Exception {
return proxyObj;
}
@SuppressWarnings("unchecked")
@Override
public Class getObjectType() {
return interfaceClass[0];
}
@Override
public boolean isSingleton() {
return true;
}
}
配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-autowire="byName">
<!-- annotation intercept-->
<bean id="testIano"
class="org.frame.base.annotation.support.EhCacheFactoryBean" init-method="init">
<property name="target">
<ref bean = "testI"/>
</property>
</bean>
<!-- 原始结构 -->
<bean id="testI" class ="org.frame.base.annotation.intercept.Test"/>
</beans>
测试代码如下:
ApplicationContext cxt = new ClassPathXmlApplicationContext(new String[]{"annotation/ano.xml"});
//TestI testI = (TestI) cxt.getBean("testI");
TestI testI = (TestI) cxt.getBean("testIano");
int a = 10;
int b = 11;
System.out.println(testI.add(a, b));
System.out.println(testI.add(a, b));
System.out.println(testI.xx(a));
System.out.println(testI.xx(a));
可以看到配置了Ehcache的方法实现了缓存功能。