package com.ciant.techgallery.transaction; import java.lang.reflect.Constructor; import java.lang.reflect.Proxy; import java.util.HashMap; import java.util.Map; /** * Creates Services intances. All services must be singletons and can be or not Transactional * * @author bcarneiro * */ public class ServiceFactory { private static Map<String, Object> cache = new HashMap<String, Object>(); /** * Creates a service instance following the rules below. -If a service implementation has * Transactional annotation should be returned a new Transactional Proxy for the implementation * -Else create a plain instance of implementation class * * @param interfac return type * @param implementation what implementation will be * @return new Service based on the rules above */ @SuppressWarnings("unchecked") public static <T> T createServiceImplementation(Class<T> interfac, Class<?> implementation) { String key = implementation.getName(); if (cache.containsKey(key)) { return (T) cache.get(key); } else if (implementation.getAnnotation(Transactional.class) != null) { T proxy = (T) Proxy.newProxyInstance(interfac.getClassLoader(), new Class[] {interfac}, new TransactionalInvocationHandler(implementation)); cache.put(key, proxy); return proxy; } else { try { Constructor<T> constructor = (Constructor<T>) implementation.getDeclaredConstructor(); constructor.setAccessible(true); T newInstance = (T) constructor.newInstance(); cache.put(key, newInstance); return newInstance; } catch (Exception e) { throw new RuntimeException(e); } } } }