使用Spring AOP横切的方式实现模拟缓存

Spring AOP 可以灵活地切入目标层的方法,控制或者拦截目标方法的运行。本次通过这种机制,控制service层执行读取数据库资源的方法,实现缓存。

步骤:先从缓存区查找。如果缓存里有则返回结果。若查询不到,则去执行原方法去数据库中查询对应的数据,并将加载出的数据存入缓存区。如果是增、删、改的操作,先清除缓存里的数据,然后与数据库交互

注意:此实例未连接数据库

实例

实体类

package com.ss.model;
 
/**
* <p>Title: User</p>  
* <p>Description: User实体</p>  
* @author Jack.Hu
* <p> @date 2018年11月18日</p>
 */
public class User implements Serializable  {
	private Long u_id;
	private String u_name;
	private String u_sex;
	
	public User(Long u_id, String u_name, String u_sex) {
		this.u_id = u_id;
		this.u_name = u_name;
		this.u_sex = u_sex;
	}
	public User() {
		
	}
	@Override
	public String toString() {
		return "User [u_id=" + u_id + ", u_name=" + u_name + ", u_sex=" + u_sex + "]";
	}
	public Long getU_id() {
		return u_id;
	}
	public void setU_id(Long u_id) {
		this.u_id = u_id;
	}

	public String getU_name() {
		return u_name;
	}
	public void setU_name(String u_name) {
		this.u_name = u_name;
	}
	public String getU_sex() {
		return u_sex;
	}
	public void setU_sex(String u_sex) {
		this.u_sex = u_sex;
	}
}

aop配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd" default-autowire="byType">

		<context:component-scan base-package="com.ss"/>
		<!-- 自动代理 -->
        <aop:aspectj-autoproxy/>
        <!-- 注册需要被横切的类 -->
        <bean id="userService" class="com.ss.service.UserServiceImpl"/>
        <!-- 注册切面类 -->
        <bean id="userAspect" class="com.ss.aop.Aspect"/>
        
        <aop:config>
        		<aop:aspect id="myAspect" ref="userAspect">
        				<aop:pointcut expression="execution(public * com.ss.service..*.*(..))" id="aspect"/>
        				<aop:before method="before" pointcut-ref="aspect"/>
        				<aop:after method="after" pointcut-ref="aspect"/>
        				<aop:around method="around" pointcut-ref="aspect"/>
        				<aop:after-returning method="returning" pointcut-ref="aspect"/>
        				<aop:after-throwing method="throwing" pointcut-ref="aspect"/>
        		</aop:aspect>
        </aop:config>
</beans>

aop切面类

package com.ss.aop;
    
import java.util.HashMap;
import java.util.Map;
    
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
    
import com.ss.model.User;
    
/**
 * 
 * <p>Title:  Aspect</p>  
 * <p>Description: 切面类</p>  
 * @author Jack.Hu
 * <p> @date 2018年11月18日</p>
 */
public class Aspect {

		// 缓存
	private Map<Integer, User> cache = new HashMap<Integer, User>();
		
	public void before (JoinPoint jp) {
			System.out.println("before:" + jp.getSignature());
		}
		
		public void after (JoinPoint jp) {
			System.out.println("after:" + jp.getSignature());
		}
		
		public void returning (JoinPoint jp) {
			System.out.println("returning:" + jp.getSignature());
		}
		
		public void throwing (JoinPoint jp) {
			System.out.println("throwing:" + jp.getSignature());
		}
		
		public Object around (ProceedingJoinPoint pj) {
			String name = pj.getSignature().getName();
			Object[] param = pj.getArgs();
			if(name.equals("selectUser")){
				if(null != cache.get(param[0])){
					return cache.get(param[0]);
				}else{
					try {
						 User user = (User) pj.proceed(pj.getArgs());
						cache.put((Integer)param[0], user);
						return cache.get(param[0]);
					} catch (Throwable e) {
						e.printStackTrace();
					}
				}
			}else{
				try {
					cache.clear(); // 清空缓存
					Object proceed = pj.proceed(pj.getArgs());
					return proceed;
				} catch (Throwable e) {
					e.printStackTrace();
				}
			}
			return null;
		}
    }

dao包接口

package com.ss.dao;
    
import com.ss.model.User;
   
    /**
    * 
    * <p>Title: IUserDao</p>  
    * <p>Description: UserDao接口</p>  
    * @author Jack.Hu
    * <p> @date 2018年11月18日</p>
     */
    public interface IUserDao {
		public User selectUser(Long userId);
    }

dao包实现类

package com.ss.dao;

import java.util.HashMap;
import java.util.Map;

import com.ss.model.User;

/**
* 
* <p>Title: UserDaoImpl</p>  
* <p>Description: UserDao包实现类</p>  
* @author Jack.Hu
* <p> @date 2018年11月18日</p>
 */
public class UserDaoImpl  implements IUserDao{

	// 模拟数据库的数据
	private final static Map<Long, User> users = new HashMap<Long, User>();
	static {
		users.put(12L, new User("张三",12L)); // 简单写两条数据
		users.put(23L, new User("李四",23L));
	}
	
	@Override
	public User selectUser(Long userId) {
		System.out.println(userId + " selectUser method successful operation。。。。。。。");
		return users.get(userId);
	}
}

service层接口

package com.ss.service;

import org.springframework.stereotype.Service;

/**
* 
* <p>Title: IUserService</p>  
* <p>Description: UserService接口</p>  
* @author Jack.Hu
* <p> @date 2018年11月18日</p>
*/
import com.ss.model.User;

public interface IUserService {
	User selectUser(Long userId);
}

service层实现类/需要被横切

package com.ss.service;
    
import com.ss.dao.IUserDao;
import com.ss.dao.UserDaoImpl;
import com.ss.model.User;
   
/**
 * 
 * <p>Title: UserServiceImpl</p>  
 * <p>Description: UserService实现类</p>  
 * @author Jack.Hu
 * <p> @date 2018年11月18日</p>
 */
public class UserServiceImpl implements IUserService {
		
	private IUserDao userDao = new UserDaoImpl();
		
	@Override
	public User selectUser(Long userId) {
		return userDao.selectUser(userId);
	}
}

测试类

package com.ss.testCache;
    
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
    
import com.ss.model.User;
    
public class TestUser {

	@Test
	public void test(){
		// 加载配置文件
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("aopAspect.xml");
		IUserService service = context.getBean(IUserService.class);
		// 查询两条相同的数据
		User user = service.selectUser(12L);
		User user1 = service.selectUser(12L);
		System.out.println(user); 
		System.out.println(user1);
		// 判断两个对象地址,如果返回true代表缓存起到作用
		System.out.println(user == user1);   // 返回为true
	}
}

以下是我开发的小程序,感兴趣的小伙伴可以扫一扫

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值