Spring bean reflection

This commit is contained in:
crusader 2017-06-30 14:08:08 +09:00
parent e232a6327c
commit 0b5eb2f439
2 changed files with 238 additions and 0 deletions

View File

@ -0,0 +1,194 @@
package com.loafle.overflow.proxy;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by crusader on 17. 6. 30.
*/
@Component
public class ServiceInvoker {
@Autowired
private ApplicationContext context;
private ObjectMapper objectMapper;
private Map<String, Cache> serviceCacheMap;
private ServiceInvoker() {
objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
serviceCacheMap = new HashMap<>();
}
private static class Cache {
private ServiceCache serviceCache;
private Map<String, MethodCache> methodCacheMap;
private Cache(Object bean) {
serviceCache = new ServiceCache();
serviceCache.bean = bean;
methodCacheMap = new HashMap<>(10);
}
private Object getBean() {
return serviceCache.bean;
}
private MethodCache getMethodCache(String methodName) throws NoSuchMethodException, ClassNotFoundException {
MethodCache methodCache = methodCacheMap.get(methodName);
if (null != methodCache) {
return methodCache;
}
Method method = getMethod(methodName);
if (null == method) {
throw new NoSuchMethodException();
}
methodCache = new MethodCache();
methodCacheMap.put(methodName, methodCache);
methodCache.method = method;
methodCache.returnClazz = method.getReturnType();
int paramCount = method.getParameterCount();
if (0 == paramCount) {
return methodCache;
}
methodCache.parameterCaches = new ParameterCache[paramCount];
ParameterCache parameterCache = null;
Type[] parameterTypes = method.getGenericParameterTypes();
Type parameterType = null;
ParameterizedType parameterizedType = null;
Type[] actualTypeArguments = null;
for (int i = 0; i < paramCount; i++) {
parameterCache = new ParameterCache();
methodCache.parameterCaches[i] = parameterCache;
parameterType = parameterTypes[i];
if (parameterType instanceof ParameterizedType) {
parameterizedType = (ParameterizedType)parameterType;
parameterCache.clazz = Class.forName(parameterizedType.getRawType().getTypeName());
actualTypeArguments = parameterizedType.getActualTypeArguments();
if (null != actualTypeArguments && 0 < actualTypeArguments.length) {
parameterCache.genericClazzes = new Class<?>[actualTypeArguments.length];
for (int j = 0; j < actualTypeArguments.length; j++) {
parameterCache.genericClazzes[j] = Class.forName(actualTypeArguments[j].getTypeName());
}
}
} else {
parameterCache.clazz = Class.forName(parameterType.getTypeName());
}
}
return methodCache;
}
private Method getMethod(String methodName) {
Class<?> clazz = AopUtils.getTargetClass(serviceCache.bean);
Method[] methods = clazz.getMethods();
Method targetMethod = null;
for(Method m : methods){
if (methodName.equals(m.getName())) {
targetMethod = m;
break;
}
}
return targetMethod;
}
private static class ServiceCache {
private Object bean;
private Map<String, MethodCache> methodCacheMap;
}
private static class MethodCache {
private Method method;
private Class returnClazz;
private ParameterCache[] parameterCaches;
}
private static class ParameterCache {
private Class clazz;
private Class[] genericClazzes;
}
}
private Cache getServiceCache(String serviceName) {
Cache serviceCache = serviceCacheMap.get(serviceName);
if (null == serviceCache) {
Object bean = context.getBean(serviceName);
serviceCache = new Cache(bean);
serviceCacheMap.put(serviceName, serviceCache);
}
return serviceCache;
}
private Object getValue(Cache.ParameterCache parameterCache, String json) throws IOException {
Object result = null;
if (List.class == parameterCache.clazz) {
result = objectMapper.readValue(json, objectMapper.getTypeFactory().constructCollectionType(List.class, parameterCache.genericClazzes[0]));
} else if (Map.class == parameterCache.clazz) {
} else {
result = objectMapper.readValue(json, parameterCache.clazz);
}
return result;
}
private Object[] getParameters(Cache.ParameterCache[] parameterCaches, List<String> params) throws IOException {
if (null == parameterCaches || null == params) {
return null;
}
if (parameterCaches.length != params.size()) {
throw new IllegalArgumentException();
}
Object[] result = new Object[parameterCaches.length];
for (int i = 0; i < parameterCaches.length; i++) {
result[i] = getValue(parameterCaches[i], params.get(i));
}
return result;
}
public String invoke(String serviceName, String methodName, List<String> params) throws NoSuchMethodException, ClassNotFoundException, IOException, InvocationTargetException, IllegalAccessException {
Cache serviceCache = getServiceCache(serviceName);
Cache.MethodCache methodCache = serviceCache.getMethodCache(methodName);
Object[] parameters = null;
if (null != methodCache.parameterCaches && 0 < methodCache.parameterCaches.length) {
parameters = getParameters(methodCache.parameterCaches, params);
}
Object result = methodCache.method.invoke(serviceCache.getBean(), parameters);
String jsonInString = objectMapper.writeValueAsString(result);
return jsonInString;
}
}

View File

@ -0,0 +1,44 @@
package com.loafle.overflow.proxy;
import com.loafle.overflow.module.target.service.TargetDiscoveryService;
import com.loafle.overflow.spring.AppConfig;
import com.loafle.overflow.spring.JdbcConfiguration;
import com.loafle.overflow.spring.MailConfiguration;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.*;
/**
* Created by crusader on 17. 6. 30.
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {AppConfig.class, JdbcConfiguration.class, MailConfiguration.class})
public class ServiceInvokerTest {
@Autowired
private ServiceInvoker serviceInvoker;
@Test
public void invoke() throws Exception {
List<String> params = new ArrayList<>(2);
params.add("[{\"id\": 1," +
"\"ip\":2312132112," +
"\"mac\":12312312," +
"\"os\": \"Windows\"," +
"\"target\":true}]");
params.add("{\"id\": 1," +
"\"ip\":2312132112," +
"\"probeKey\":\"sdfsdfsdfsdfsd\"}");
serviceInvoker.invoke("TargetDiscoveryService", "saveAllTarget", params);
}
}