IOC的实现主要是基于注解或者配置文件了解关系,缓存被依赖类,在访问时实时构建.
主要实现类:
package iocTest;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import com.alibaba.fastjson.JSON;
public class BootStrap {
public static void main(String[] args) {
loadConfig();
createBeanCache();
// invoke("testAction", "say", "Hello World!");
// invokeInParallel("testAction", "say", "Hello World!", 100);
}
public static IocConfig iocConfig;
public static Map<String, IocRely> unmodifiableMap;
public static Map<String, Object> cachedObject;
@SuppressWarnings("unchecked")
private static void loadConfig() {
String content = null;
try {
content = FileUtils.readFileToString(new File("config/iocTest.json"), "utf-8");
} catch (IOException e) {
e.printStackTrace();
}
if (StringUtils.isEmpty(content)) {
throw new Error();
}
Map<String, Object> iocConfigMap = JSON.parseObject(content);
Boolean isAutoLoad = (Boolean) iocConfigMap.get("isAutoLoad");
Map<String, Object> iocTestConfig=(Map<String, Object>) iocConfigMap.get("iocTest");
Function<Map<String, Object>, IocConfig> initConfig = (configMap) -> (new IocConfig() {
{
Map<String, Object> config = (Map<String, Object>) configMap.get("conifg");
if (null != config.get("maxCacheSize"))
this.setSameActionMaxSize((Integer) config.get("sameActionMaxSize"));
}
});
iocConfig = initConfig.apply(iocTestConfig);
if (isAutoLoad) {
//扫描注解
loadFromFile((String) iocConfigMap.get("rootPath"));
} else {
//通过json配置文件
loadFromJSON(iocTestConfig);
}
}
private static void loadFromFile(String basicPath) {
String rootPath = ClassLoader.getSystemResource(".").getPath() + basicPath;
File rootFile = new File(rootPath);
List<String> fileList = new ArrayList<String>();
try {
listFiles(rootFile, fileList);
} catch (IOException e) {
e.printStackTrace();
}
List<String> classes = fileList.stream().map(filestr -> filestr.substring(rootPath.length()).replace("\\", "."))
.collect(Collectors.toList());
Map<String,IocRely> resultMap=new HashMap<String,IocRely>();
classes.forEach(class_ -> analysisClass(basicPath + "." + class_,resultMap));
unmodifiableMap= Collections.unmodifiableMap(resultMap);
}
private static void analysisClass(String path,Map<String,IocRely> resultMap) {
Class<?> class_ = null;
try {
class_ = Class.forName(path);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
String name=StringUtils.uncapitalize(path.substring(path.lastIndexOf(".")+1));
IocRely iocRely=new IocRely(name, path);
Field[] fields = class_.getDeclaredFields();
List<String> delys=new ArrayList<String>();
if (ArrayUtils.isNotEmpty(fields)) {
for (int i = 0, length = fields.length; i < length; i++) {
//TODO
//Inject inject = fields[i].getAnnotation(Inject.class);
delys.add(fields[i].getName());
}
}
iocRely.setRelys(delys);
resultMap.put(name, iocRely);
}
private static List<String> listFiles(File rootFile, List<String> fileList) throws IOException {
File[] allFiles = rootFile.listFiles();
for (File file : allFiles) {
if (file.isDirectory()) {
listFiles(file, fileList);
} else {
String path = file.getAbsolutePath();
fileList.add(path.substring(0, path.lastIndexOf(".")));
}
}
return fileList;
}
@SuppressWarnings("unchecked")
private static void loadFromJSON(Map<String, Object> iocTestConfig) {
// init relyMap
Function<Map<String, Object>, Map<String, IocRely>> initRelyMap = (configMap) -> {
HashMap<String, IocRely> resultMap = new HashMap<String, IocRely>();
// init basic
List<Map<String, Object>> beans = (List<Map<String, Object>>) configMap.get("beans");
beans.forEach(bean -> {
bean.entrySet().forEach(entry -> {
String beanName = entry.getKey();
Object beanContent = entry.getValue();
if (beanContent instanceof java.lang.String) {
resultMap.put(beanName, new IocRely(beanName, (String) beanContent));
} else {
Map<String, Object> contents = (Map<String, Object>) beanContent;
IocRely iocRely = new IocRely(beanName, (String) contents.get("path"));
Consumer<String> getValues = (key) -> {
if (contents.containsKey(key)) {
try {
IocRely.class.getDeclaredField(key).set(iocRely, contents.get(key));
} catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException
| SecurityException e) {
e.printStackTrace();
}
}
};
getValues.accept("isRequire");
getValues.accept("isSingleton");
getValues.accept("isCache");
resultMap.put(beanName, iocRely);
}
});
});
// init rely
Map<String, List<String>> shimList = (Map<String, List<String>>) configMap.get("shim");
shimList.entrySet().forEach(shim -> {
IocRely iocRely = null;
if ((iocRely = resultMap.get(shim.getKey())) != null) {
iocRely.setRelys(shim.getValue());
}
});
return resultMap;
};
unmodifiableMap = Collections.unmodifiableMap(initRelyMap.apply(iocTestConfig));
}
private static void createBeanCache() {
cachedObject = new ConcurrentHashMap<String, Object>(unmodifiableMap.size());
unmodifiableMap.entrySet().forEach(entry -> {
List<String> relays = entry.getValue().getRelys();
if (null != relays && !relays.isEmpty()) {
relays.forEach(relay -> {
if (!cachedObject.containsKey(relay) && entry.getValue().isCache) {
inject(relay, true);
}
});
}
});
}
private static Object inject(String name, Boolean isCache) {
Object itemObject = null;
if (null == (itemObject = cachedObject.get(name))) {
IocRely iocRely = null;
if (null != (iocRely = unmodifiableMap.get(name))) {
try {
itemObject = Class.forName(iocRely.path).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e1) {
e1.printStackTrace();
}
List<String> relys = iocRely.getRelys();
if (null != relys && !relys.isEmpty()) {
for (int i = 0, length = relys.size(); i < length; i++) {
String currentName = relys.get(i);
try {
Field field = itemObject.getClass().getDeclaredField(currentName);
field.setAccessible(true);
field.set(itemObject, inject(currentName, true));
} catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException
| SecurityException e) {
e.printStackTrace();
}
}
}
if (iocRely.isCache && isCache)
cachedObject.put(name, itemObject);
} else {
System.out.println(name);
throw new Error("unexpected class");
}
}
return itemObject;
}
private static void invoke(String className, String methodName, Object queryParams) {
if (StringUtils.isAnyEmpty(className, methodName))
return;
Object itemObject = inject(className, false);
try {
itemObject.getClass().getMethod(methodName, queryParams.getClass()).invoke(itemObject, queryParams);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
| SecurityException e) {
e.printStackTrace();
}
}
private static void invokeInParallel(String className, String methodName, Object queryParams, int threadNumber) {
if (threadNumber > 0) {
for (int i = 0; i < threadNumber; i++) {
new Thread(() -> {
BootStrap.invoke(className, methodName, queryParams);
}).start();
}
}
}
}
注解类:
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Inject {
String value() default "default" ;
boolean isRequire() default true;
boolean isCache() default true;
boolean isSingleton() default true;
}
配置文件:
{
"isAutoLoad":false,
"rootPath":"test",
"iocTest": {
"beans": [
{
"testAction": {
"path": "test.TestAction",
"isSingleton": true
}
},
{
"testService": "test.TestService"
},
{
"testDao1": "test.TestDao1"
},
{
"testDao2": {
"path": "test.TestDao2",
"isCache": false
}
}
],
"shim": {
"testAction": [
"testService"
],
"testService": [
"testDao1",
"testDao2"
]
},
"conifg": {
"sameActionMaxSize": 5
}
}
}