在学习jdk的动态代理的时候我们需要记住一个类java.lang.reflect.Proxy和一个接口java.lang.reflect.InvocationHandler。InvocationHandler将jdk对类的处理以方法参数的方式暴露给我们,这个方法是
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {},以下是三个参数的说明
proxy:代理对象
method:被代理对象的方法,即被实际访问的方法
args:被实际访问的方法的参数
这里的关键就是method和args,我们可以对args和method进行处理,比如判断方法的参数是否是和上次调用时的一模一样,如果参数一样,方法也一样,那么我们就可以从缓存中去获取结果,比如mybatis的缓存就是这样的,一下是模拟的整个过程!
项目结构
User.java
package com.ss.entity;
public class User {
private Long userId;
private String userName;
private String nickName;
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
@Override
public String toString() {
return "User [userId=" + userId + ", userName=" + userName + ", nickName=" + nickName + "]";
}
public User(){
}
public User(Long userId, String userName, String nickName) {
this.userId = userId;
this.userName = userName;
this.nickName = nickName;
}
}
UserDao.java
package com.ss.dao;
import com.ss.entity.User;
public interface UserDao {
Integer createUser(User user);
Integer deleteUser(User user);
Integer updateUser(User user);
User retrieveUser(Long userId);
}
UserDaoImpl.java
package com.ss.dao;
import java.lang.reflect.Proxy;
import com.ss.db.Cache;
import com.ss.db.DBProcess;
import com.ss.db.MySQL;
import com.ss.entity.User;
public class UserDaoImpl implements UserDao {
/**
* 通过proxy生成的DBProcess的代理对象
* new Cache(new MySQL())是关键
*/
private DBProcess proxy = (DBProcess) Proxy.newProxyInstance(DBProcess.class.getClassLoader(), new Class[]{DBProcess.class}, new Cache(new MySQL()));
@Override
public Integer createUser(User user) {
System.out.println("createUser in UserDaoImpl is invoked successfully..................");
proxy.insert(user);
return 1;
}
@Override
public Integer deleteUser(User user) {
System.out.println("deleteUser in UserDaoImpl is invoked successfully..................");
proxy.delete(user);
return 1;
}
@Override
public Integer updateUser(User user) {
System.out.println("updateUser in UserDaoImpl is invoked successfully..................");
proxy.update(user);
return 1;
}
@Override
public User retrieveUser(Long userId) {
System.out.println("retrieveUser in UserDaoImpl is invoked successfully..................");
return proxy.select(userId);
}
}
DBProcess.java
package com.ss.db;
import com.ss.entity.User;
public interface DBProcess {
Integer insert(User user);
Integer delete(User user);
Integer update(User user);
User select(Long userId);
}
Cache.java
package com.ss.db;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class Cache implements InvocationHandler{
//缓存容器
private final static Map<Long, Object> cache = new HashMap<>();
private DBProcess db;
//只提供有参的构造器给外界,使得外界必须在获取对象的同时初始化属性
public Cache(DBProcess db) {
this.db = db;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//1.BootStrapClassLoader 2.ExtClassLoader 3.AppClassLoader 4.自定义ClassLoader
if(method.getName().equalsIgnoreCase("select")){//如果时查询方法则进行缓存处理
if(cache.get(args[0])!=null) return cache.get(args[0]);///相同的参数则从缓存中获取
else{//如果缓存中没有则执行数据库查询并进行缓存
Object obj = method.invoke(db, args);
cache.put((Long)args[0], obj);
return obj;
}
}else{
cache.clear();
Object obj = method.invoke(db, args);
return obj;
}
}
}
MySQL.java
package com.ss.db;
import java.util.Random;
import com.ss.entity.User;
public class MySQL implements DBProcess{
//两个数组自行初始化,长度一样即可
private static String[] names = {};
private static String[] nickNames = {};
@Override
public Integer insert(User user) {
System.out.println(user + " is inserted to mysql successfullly............");
return 1;
}
@Override
public Integer delete(User user) {
System.out.println(user + " is deleted from mysql successfullly............");
return 1;
}
@Override
public Integer update(User user) {
System.out.println(user + " is updated to mysql successfullly............");
return 1;
}
@Override
public User select(Long userId) {
System.out.println("............ MySQL's select is invoked ...........");
Integer random = new Random().nextInt(10);
return new User(userId, names[random], nickNames[random]);
}
}
UserServiceImpl.java
package com.ss.service;
import org.junit.Test;
import com.ss.dao.UserDao;
import com.ss.dao.UserDaoImpl;
import com.ss.entity.User;
public class UserServiceImpl {
@Test
public void testCache(){
UserDao dao = new UserDaoImpl();
User user1 = dao.retrieveUser(12L);
User user2 = dao.retrieveUser(12L);
System.out.println(user1);
System.out.println(user1 == user2);
dao.deleteUser(new User(1L, "cache", "cc"));
User user3 = dao.retrieveUser(12L);
System.out.println(user3);
}
}
执行testCache方法,结果如下所示