package com.snail.proxyexam;
public interface EmployeeDAO {
Employee create(Employee emp);
Employee findById(String id);
void update(Employee emp);
void delete(String id);
}
package com.snail.proxyexam;
import java.io.Serializable;
public class Employee implements Serializable {
private static final long serialVersionUID = -4149357252932523956L;
private String id;
private String name;
private String sex;
public Employee(String id, String name, String sex) {
this.id = id;
this.name = name;
this.sex = sex;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String toString() {
return "{" + id + "," + name + "," + sex + "}";
}
}
package com.snail.proxyexam;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class EmployeeDAOImpl implements EmployeeDAO {
// DBのつもり
private static final Map<String, Employee> mockDB;
static {
mockDB = Collections.synchronizedMap(new HashMap<String, Employee>());
mockDB.put("1234", new Employee("1234", "はる はなこ", "female"));
mockDB.put("2345", new Employee("2345", "やまだ たろう", "male"));
}
@Override
public Employee create(Employee emp) {
emp.setId("9999");
mockDB.put(emp.getId(), emp);
System.out.println(emp.getId() + "をDB登録しました");
return emp;
}
@Override
public Employee findById(String id) {
System.out.println(id + "をDB検索しました");
return mockDB.get(id);
}
@Override
public void update(Employee emp) {
mockDB.put(emp.getId(), emp);
System.out.println(emp.getId() + "をDB更新しました");
}
@Override
public void delete(String id) {
mockDB.remove(id);
System.out.println(id + "をDB削除しました");
}
}
package com.snail.proxyexam;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.apache.commons.beanutils.PropertyUtils;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
public class DAOFactory {
@SuppressWarnings("unchecked")
public static <T> T createProxy(Class<T> inf, final T obj) {
return (T) Proxy.newProxyInstance(obj.getClass().getClassLoader(),
new Class[]{inf}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
if (method.getName().startsWith("create")) {
Object retObj = method.invoke(obj, args);
addOrUpdateCache(retObj);
return retObj;
} else if (method.getName().startsWith("findById")) {
CacheManager manager = CacheManager.getInstance();
Cache cache = manager.getCache("EntityCache");
Element element = cache.get(args[0]);
if (element == null) {
Object retObj = method.invoke(obj, args);
addOrUpdateCache(retObj);
return retObj;
} else {
System.out.println("おめでとうございます!!! キャッシュにヒットしました。DB検索しません");
return element.getObjectValue();
}
} else if (method.getName().startsWith("update")) {
Object retObj = method.invoke(obj, args);
addOrUpdateCache(args[0]);
return retObj;
} else if (method.getName().startsWith("delete")) {
Object retObj = method.invoke(obj, args);
CacheManager manager = CacheManager.getInstance();
Cache cache = manager.getCache("EntityCache");
cache.remove(args[0]);
System.out.println(args[0] + "をキャッシュから削除しました");
return retObj;
}
return method.invoke(obj, args);
}
private void addOrUpdateCache(Object obj) {
if (obj == null) {
return;
}
try {
CacheManager manager = CacheManager.getInstance();
Cache cache = manager.getCache("EntityCache");
Object id = PropertyUtils.getProperty(obj, "id");
cache.put(new Element(id, obj));
System.out.println(id + "をキャッシュに登録しました");
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
}
}
CacheManager manager = CacheManager.getInstance(); Cache cache = manager.getCache("EntityCache");
<ehcache>
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
<cache name="EntityCache"
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
/>
</ehcache>
cache.put(new Element(key, value));
Element element = cache.get(key);
cache.remove(key);
package com.snail.proxyexam;
public class App {
public static void main(String[] args) {
EmployeeDAO dao = DAOFactory.createProxy(EmployeeDAO.class, new EmployeeDAOImpl());
System.out.println("***** 検索処理(1) *****");
Employee emp1 = dao.findById("1234");
System.out.println(emp1);
System.out.println("***** 更新処理 *****");
emp1.setName("あき はなこ");
dao.update(emp1);
System.out.println("***** 検索処理(2) *****");
Employee emp2 = dao.findById("1234");
System.out.println(emp2);
System.out.println("***** 削除処理 *****");
dao.delete("1234");
System.out.println("***** 検索処理(3) *****");
Employee emp3 = dao.findById("1234");
System.out.println(emp3);
}
}
***** 検索処理(1) ***** 1234をDB検索しました 1234をキャッシュに登録しました {1234,はる はなこ,female} ***** 更新処理 ***** 1234をDB更新しました 1234をキャッシュに登録しました ***** 検索処理(2) ***** おめでとうございます!!! キャッシュにヒットしました。DB検索しません {1234,あき はなこ,female} ***** 削除処理 ***** 1234をDB削除しました 1234をキャッシュから削除しました ***** 検索処理(3) ***** 1234をDB検索しました null
DB | Cache | ||
1 | ***** 検索処理(1) ***** | 検索 | 登録 |
2 | ***** 更新処理 ***** | 更新 | 更新 |
3 | ***** 検索処理(2) ***** | ---- | 読出 |
4 | ***** 削除処理 ***** | 削除 | 削除 |
5 | ***** 検索処理(3) ***** | 検索 | ---- |