import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface EnableMyCache {
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyCacheable {
String cacheKey();
}
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Component
public class MyBeanPostProcessor implements ApplicationContextAware, BeanPostProcessor {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 获取 添加了 "EnableMyCache" 注解的 bean,然后 返回该 bean 的 cglib 代理对象
EnableMyCache declaredAnnotation = bean.getClass().getDeclaredAnnotation(EnableMyCache.class);
if( declaredAnnotation == null ){
return bean;
}
MethodInterceptor methodInterceptor = new MethodInterceptor() {
@Override
public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
// 首先查询缓存中有没有,有直接返回,没有再调用目标方法获取结果返回
MyCacheable annotation = method.getDeclaredAnnotation(MyCacheable .class);
if( annotation == null ){
return methodProxy.invokeSuper(object, args);
}
String cacheKey = annotation.cacheKey();
Object result = MyCache.get(cacheKey);
if( result != null ){
return result;
}
result = methodProxy.invokeSuper(object, args);
MyCache.put( cacheKey,result );
return result;
}
};
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass( bean.getClass());
enhancer.setCallback( methodInterceptor );
Object beanPoxy = enhancer.create();
BeanUtils.copyProperties( bean,beanPoxy );
return beanPoxy;
}
}
import org.springframework.stereotype.Component;
@Component
@EnableMyCache
@Getter
@Setter
public class TestService {
@MyCacheable( cacheKey="xxxxxxxxxxxxxxx" )
public Object get(){
System.out.print( "模拟查询数据库...");
return new Object();
}
}
import com.alibaba.fastjson.JSONObject;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest( webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class CommonTest {
@Autowired
private TestService testService;
@Test
public void test(){
System.out.println( JSONObject.toJSonString( this.testService.get() ) );
System.out.println( JSONObject.toJSonString( this.testService.get() ) );
System.out.println( JSONObject.toJSonString( this.testService.get() ) );
System.out.println( JSONObject.toJSonString( this.testService.get() ) );
}
}
坑:
1. TestService 得使用 @Getter、@Setter 注解,然后生成 TestService 的 cglib 代理对象后使用 BeanUtils.copyProperties( bean,beanPoxy ) ,否则 TestService 中的 @Autowired 注入不进来。
2. TestService 中的方法中供内部使用的 ,也就是使用 this.调用的方法必须是 public 的,否则 MethodInterceptor 不生效。



