利用AOP實現一個簡單的快取儲存、清除的工具
阿新 • • 發佈:2018-11-01
基本要求:利用aop實現一個簡單的快取儲存、清除的工具,從實際使用上來說,切面應該在provider層。在service層方法呼叫和資料庫查詢之間生效。為了簡化過程,不要求與資料庫互動,資料可以隨機生成,不要求使用redis等中介軟體,可以直接快取到記憶體中。
程式碼實現非常的基礎,能夠很好的理解AOP以及快取的基本原理,想要深入理解可以去查閱更多的資料。僅供自己學習。
1、實體類:
public class Student { String id; String name; double score; @Override public String toString() { return "Student [id=" + id + ", name=" + name + ", score=" + score + "]"; } }
2、自定義註解:
import java.lang.annotation.*; //自定義快取註解 獲取快取 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface GetCacheable { } //自定義快取註解 更新快取註解 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 UpdateCacheEvict { } //自定義快取註解 清空所有快取 import java.lang.annotation.*; @Target({ ElementType.METHOD, ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ClearCache { }
3、AOP快取切面實現:
import java.util.Map; import org.apache.commons.lang.StringUtils; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import java.util.Collections; import java.util.HashMap; //aop配合cache註解實現快取,AOP快取切面 @Component @Aspect public class AopCacheAspect { private static final Logger logger = LoggerFactory.getLogger(AopCacheAspect.class); // 為了執行緒安全,使用Collections.synchronizedMap(new HashMap()); private static Map<String, Object> aopCahche = Collections.synchronizedMap(new HashMap<String, Object>()); @Around(value = "@annotation(com.everhomes.learning.demos.cache.djm.service.GetCacheable)") public Object getCache(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { Object result = null; String key = generateKey(proceedingJoinPoint); result = aopCahche.get(key); if (result == null) { result = proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs()); aopCahche.put(key, result); } logger.info("get cache! key={},value={}", key, result); return result; } @Around("@annotation(com.everhomes.learning.demos.cache.djm.service.UpdateCacheEvict)") public Object evict(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { Object result = null; String key = generateKey(proceedingJoinPoint); result = aopCahche.get(key); if (result != null) { aopCahche.remove(key); } logger.info("evict cache! key={},result = {}", key, result); return proceedingJoinPoint.proceed(); } @Around("@annotation(com.everhomes.learning.demos.cache.djm.service.ClearCache)") public void clear(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { aopCahche = Collections.synchronizedMap(new HashMap<String, Object>()); } // 生成快取 key 可以選擇不同生成key值的方式 private String generateKey(ProceedingJoinPoint pJoinPoint) { StringBuffer cacheKey = new StringBuffer(); String type = pJoinPoint.getArgs().getClass().getSimpleName(); cacheKey.append(StringUtils.join(pJoinPoint.getArgs(), "::")); cacheKey.append(type); return cacheKey.toString(); } }
4、controller層實現:
public interface StudentProvider {
Student getStudentById(String id);
Student updateStudentById(String id);
void clearCache();
}
@RestController
@RequestMapping("/student")
public class StudentController {
@Autowired
private StudentService studentService;
@RequestMapping("/getStudentById")
public Student getStudentById(String id) {
Student student = studentService.getStudentById(id);
return student;
}
@RequestMapping("/updateStudentById")
public Student updateStudentById(String id) {
Student student = studentService.updateStudentById(id);
return student;
}
@RequestMapping("/clearCache")
public void clearCache(String id) {
studentService.clearCache();
}
}
5、Service層實現:
import com.everhomes.learning.demos.cache.djm.controller.Student;
public interface StudentService {
Student getStudentById(String id);
Student updateStudentById(String id);
void clearCache();
}
import com.everhomes.learning.demos.cache.djm.controller.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentProvider studentProvider;
@Override
public Student getStudentById(String id) {
Student student = studentProvider.getStudentById(id);
return student;
}
@Override
public Student updateStudentById(String id) {
Student student = studentProvider.updateStudentById(id);
return student;
}
@Override
public void clearCache() {
studentProvider.clearCache();
}
}
6、Provider層實現:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
public class StudentProviderImpl implements StudentProvider {
private static final Logger LOGGER = LoggerFactory.getLogger(StudentProviderImpl.class);
@GetCacheable
@Override
public Student getStudentById(String id) {
LOGGER.info("進行查詢的" + id + "沒有使用快取,模擬查詢資料庫");
Student student = new Student();
student.setId("000" + id);
student.setName("我是代號是:000" + id);
student.setScore(80);
return student;
}
@UpdateCacheEvict
@Override
public Student updateStudentById(String id) {
LOGGER.info("對" + id + "進行資料更新!");
Student student = new Student();
student.setId("000" + id);
student.setName("我是代號是:000" + id);
student.setScore(90);
return student;
}
@ClearCache
@Override
public void clearCache() {
LOGGER.info("資料清空了!");
}
}
每天努力一點,每天都在進步。