diff --git a/.gitignore b/.gitignore index bf9e148..46f6845 100644 --- a/.gitignore +++ b/.gitignore @@ -46,4 +46,5 @@ log .idea node_modules pnpm-lock.yaml +package-lock.json diff --git a/gradle.properties b/gradle.properties index b5598b5..5703da0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ GROUPSID=com.mingliqiye -ARTIFACTID=socket-utilts +ARTIFACTID=instance-factory VERSIONS=1.0.1 -MAINCLASS=com.mingliqiye.Main +MAINCLASS=com.mingliqiye.bean.Factory JDKVERSIONS=1.8 diff --git a/src/main/java/com/mingliqiye/Main.java b/src/main/java/com/mingliqiye/Main.java deleted file mode 100644 index 1f285d4..0000000 --- a/src/main/java/com/mingliqiye/Main.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.mingliqiye; - -public class Main { - /** - * @param args [] - */ - public static void main(String[] args) { - System.out.print("Hello and welcome!"); - for (int i = 1; i <= 5; i++) { - System.out.println("i = " + i); - } - } -} diff --git a/src/main/java/com/mingliqiye/bean/Component.java b/src/main/java/com/mingliqiye/bean/Component.java new file mode 100644 index 0000000..071278b --- /dev/null +++ b/src/main/java/com/mingliqiye/bean/Component.java @@ -0,0 +1,9 @@ +package com.mingliqiye.bean; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface Component { + String value() default ""; +} diff --git a/src/main/java/com/mingliqiye/bean/Factory.java b/src/main/java/com/mingliqiye/bean/Factory.java new file mode 100644 index 0000000..1b878e3 --- /dev/null +++ b/src/main/java/com/mingliqiye/bean/Factory.java @@ -0,0 +1,195 @@ +package com.mingliqiye.bean; + +import java.io.File; +import java.lang.reflect.Field; +import java.net.URL; +import java.util.Enumeration; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +public class Factory { + + public static final ConcurrentMap beans = + new ConcurrentHashMap<>(); + private static final ConcurrentMap, Object> typeBeans = + new ConcurrentHashMap<>(); + + private Factory() {} + + /** + * 自动扫描注解 + * @param c 包名所在的类 + */ + public static void autoScan(Class c) { + if (c == null) { + throw new IllegalArgumentException("Class cannot be null"); + } + Package pkg = c.getPackage(); + if (pkg == null) { + throw new IllegalArgumentException( + "Class is in the default package" + ); + } + scan(pkg.getName()); + } + + /** + * 扫描注解 + * @param basePackage 包名 + */ + public static void scan(String basePackage) { + try { + String path = basePackage.replace('.', '/'); + ClassLoader classLoader = + Thread.currentThread().getContextClassLoader(); + Enumeration resources = null; + resources = classLoader.getResources(path); + while (resources.hasMoreElements()) { + URL resource = resources.nextElement(); + File file = new File(resource.toURI()); + scanDirectory(file, basePackage); + } + injectDependencies(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static void scanDirectory(File directory, String packageName) + throws Exception { + File[] files = directory.listFiles(); + if (files == null) return; + + for (File file : files) { + if (file.isDirectory()) { + scanDirectory(file, packageName + "." + file.getName()); + } else if (file.getName().endsWith(".class")) { + String className = + packageName + '.' + file.getName().replace(".class", ""); + registerComponent(Class.forName(className)); + } + } + } + + private static void registerComponent(Class clazz) throws Exception { + if (clazz.isAnnotationPresent(Component.class)) { + Component component = clazz.getAnnotation(Component.class); + String name = component.value().isEmpty() + ? clazz.getName() + : component.value(); + Object instance = clazz.getDeclaredConstructor().newInstance(); + beans.put(name, instance); + typeBeans.put(clazz, instance); + + for (Class interfaceClass : clazz.getInterfaces()) { + typeBeans.putIfAbsent(interfaceClass, instance); + } + } + } + + private static void injectDependencies() throws Exception { + for (Object bean : beans.values()) { + for (Field field : bean.getClass().getDeclaredFields()) { + if (field.isAnnotationPresent(Inject.class)) { + Inject inject = field.getAnnotation(Inject.class); + Object dependency = findDependency( + field.getType(), + inject.value() + ); + if (dependency == null) { + throw new IllegalStateException( + "No suitable dependency found for field " + + field.getName() + + " in class " + + bean.getClass().getName() + ); + } + field.setAccessible(true); + field.set(bean, dependency); + } + } + } + } + + private static Object findDependency(Class type, String name) { + if (!name.isEmpty()) { + return beans.get(name); + } + + Object dependency = typeBeans.get(type); + if (dependency != null) { + return dependency; + } + + for (Class interfaceType : typeBeans.keySet()) { + if (type.isAssignableFrom(interfaceType)) { + return typeBeans.get(interfaceType); + } + } + + return null; + } + + /** + * 添加一个实例 + * @param object 示例对象 + */ + public static void add(Object object) { + Class clazz = object.getClass(); + String name = clazz.getName(); + beans.put(name, object); + typeBeans.put(clazz, object); + try { + injectDependencies(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * 添加一个实例 + * @param name 实例名 + * @param object 实例 + */ + public static void add(String name, Object object) { + beans.put(name, object); + typeBeans.put(object.getClass(), object); + try { + injectDependencies(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * 获取实例 + * @param objclass 实例类 + * @return T 实例 + * @param + */ + public static T get(Class objclass) { + return objclass.cast(typeBeans.get(objclass)); + } + + /** + * 获取实例 + * @param name 实例名 + * @param objclass 实例类 + * @return T 实例 + * @param + */ + public static T get(String name, Class objclass) { + return objclass.cast(beans.get(name)); + } + + /** + * 获取实例 + * @param name 实例名 + * @return Object 实例 + */ + public static Object get(String name) { + return beans.get(name); + } + + public static void main(String[] args) {} +} diff --git a/src/main/java/com/mingliqiye/bean/Inject.java b/src/main/java/com/mingliqiye/bean/Inject.java new file mode 100644 index 0000000..c882497 --- /dev/null +++ b/src/main/java/com/mingliqiye/bean/Inject.java @@ -0,0 +1,9 @@ +package com.mingliqiye.bean; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface Inject { + String value() default ""; +}