天天看点

利用AOP实现一个简单的缓存存储、清除的工具

基本要求:利用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("数据清空了!");
	}
}
           

每天努力一点,每天都在进步。