使用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
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章