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) ***** | 検索 | ---- |