Compare commits

2 Commits

Author SHA1 Message Date
f0d354a763 fix log format 2025-07-24 10:29:57 +08:00
0631fab381 support jdk8 in legacy branch 2025-07-23 23:07:09 +08:00
4 changed files with 59 additions and 140 deletions

19
pom.xml
View File

@ -6,25 +6,12 @@
<groupId>com.imyeyu.inject</groupId> <groupId>com.imyeyu.inject</groupId>
<artifactId>timi-inject</artifactId> <artifactId>timi-inject</artifactId>
<version>0.0.1</version> <version>0.0.1-legacy</version>
<properties> <properties>
<maven.compiler.source>21</maven.compiler.source> <maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target> <maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.test.skip>true</maven.test.skip> <maven.test.skip>true</maven.test.skip>
</properties> </properties>
<dependencies>
<dependency>
<groupId>com.imyeyu.io</groupId>
<artifactId>timi-io</artifactId>
<version>0.0.1</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.5.13</version>
</dependency>
</dependencies>
</project> </project>

View File

@ -0,0 +1,10 @@
package com.imyeyu.inject;
/**
* @author 夜雨
* @since 2025-07-23 22:50
*/
public interface CallbackArg<T> {
void handler(T t);
}

View File

@ -1,7 +1,5 @@
package com.imyeyu.inject; package com.imyeyu.inject;
import com.imyeyu.java.bean.CallbackArg;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -17,8 +15,6 @@ public final class InjectApp {
TimiInject injector; TimiInject injector;
boolean enableBanner = true;
/** 全局注入后监听,包括静态注入 */ /** 全局注入后监听,包括静态注入 */
final List<CallbackArg<TimiInject>> afterInjectCallbackList = new ArrayList<>(); final List<CallbackArg<TimiInject>> afterInjectCallbackList = new ArrayList<>();
@ -31,11 +27,6 @@ public final class InjectApp {
this.clazz = clazz; this.clazz = clazz;
} }
public InjectApp disableBanner() {
enableBanner = false;
return this;
}
public TimiInject injector() { public TimiInject injector() {
return injector; return injector;
} }
@ -57,12 +48,4 @@ public final class InjectApp {
public synchronized void removeAfterInjectListener(CallbackArg<TimiInject> listener) { public synchronized void removeAfterInjectListener(CallbackArg<TimiInject> listener) {
afterInjectCallbackList.remove(listener); afterInjectCallbackList.remove(listener);
} }
public boolean isEnableBanner() {
return enableBanner;
}
public void setEnableBanner(boolean enableBanner) {
this.enableBanner = enableBanner;
}
} }

View File

@ -15,12 +15,6 @@ import com.imyeyu.inject.annotation.SuperIOC;
import com.imyeyu.inject.annotation.SuperInject; import com.imyeyu.inject.annotation.SuperInject;
import com.imyeyu.inject.annotation.TimiInjectApplication; import com.imyeyu.inject.annotation.TimiInjectApplication;
import com.imyeyu.inject.annotation.Util; import com.imyeyu.inject.annotation.Util;
import com.imyeyu.io.IO;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.CallbackArg;
import com.imyeyu.utils.Time;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -31,6 +25,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.net.URI; import java.net.URI;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Comparator; import java.util.Comparator;
import java.util.Enumeration; import java.util.Enumeration;
@ -49,9 +44,6 @@ import java.util.jar.JarFile;
*/ */
public class TimiInject implements InjectFactory { public class TimiInject implements InjectFactory {
/** 日志 */
private static final Logger log = LoggerFactory.getLogger(TimiInject.class);
/** 类路径 */ /** 类路径 */
private final List<String> paths; private final List<String> paths;
@ -79,21 +71,13 @@ public class TimiInject implements InjectFactory {
private final Object iocAsyncLock = new Object(); private final Object iocAsyncLock = new Object();
private TimiInject(InjectApp app) { private TimiInject(InjectApp app) {
if (TimiJava.isEmpty(app)) { if (app == null) {
throw new NullPointerException("empty inject app"); throw new NullPointerException("not found inject app");
} }
app.injector = this; app.injector = this;
// 初始化 // 初始化
long initAt = Time.now(); long initAt = System.currentTimeMillis();
// Logo System.out.printf("Starting TimiInject %s ..%n", app.clazz);
if (app.enableBanner) {
if (IO.resourceExist(getClass(), "banner.txt")) {
log.info(IO.resourceToString(getClass(), "banner.txt"));
} else {
log.info(IO.resourceToString(getClass(), "defBanner.txt"));
}
}
log.info("Starting TimiInject {} ..", app.clazz);
List<String> scanPathList = new ArrayList<>(); List<String> scanPathList = new ArrayList<>();
objects = new HashMap<>(); objects = new HashMap<>();
iocListeners = new HashMap<>(); iocListeners = new HashMap<>();
@ -104,18 +88,18 @@ public class TimiInject implements InjectFactory {
classes = new ArrayList<>(); classes = new ArrayList<>();
try { try {
// 扫描 // 扫描
long scanAt = Time.now(); long scanAt = System.currentTimeMillis();
{ {
// 扫描包 // 扫描包
log.info("Scanning.."); System.out.println("Scanning..");
TimiInjectApplication appAnnotation = app.clazz.getAnnotation(TimiInjectApplication.class); TimiInjectApplication appAnnotation = app.clazz.getAnnotation(TimiInjectApplication.class);
if (appAnnotation == null) { if (appAnnotation == null) {
throw new NullPointerException("TimiInjectApplication can not be null, used annotation for scanner class"); throw new NullPointerException("TimiInjectApplication can not be null, used annotation for scanner class");
} }
if (TimiJava.isEmpty(appAnnotation.value())) { if (appAnnotation.value() == null || appAnnotation.value().length == 0) {
scanPathList.add(app.clazz.getPackageName()); scanPathList.add(app.clazz.getPackage().getName());
} else { } else {
scanPathList.addAll(List.of(appAnnotation.value())); scanPathList.addAll(Arrays.asList(appAnnotation.value()));
} }
// 扫描类 // 扫描类
URI baseURI = app.clazz.getProtectionDomain().getCodeSource().getLocation().toURI(); URI baseURI = app.clazz.getProtectionDomain().getCodeSource().getLocation().toURI();
@ -125,8 +109,8 @@ public class TimiInject implements InjectFactory {
} }
} }
// 控制反转 // 控制反转
log.info("Running IOC.."); System.out.println("Running IOC..");
long iocAt = Time.now(); long iocAt = System.currentTimeMillis();
{ {
// Application IOC // Application IOC
if (app.obj != null) { if (app.obj != null) {
@ -173,7 +157,7 @@ public class TimiInject implements InjectFactory {
newInstance(iocClass); newInstance(iocClass);
} }
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("IOC fail id: %s, class: %s".formatted(iocClass.id, iocClass.clazz), e); throw new RuntimeException(String.format("IOC fail id: %s, class: %s", iocClass.id, iocClass.clazz), e);
} }
} }
if (hasAsyncIOC && iocAsyncRunning != 0) { if (hasAsyncIOC && iocAsyncRunning != 0) {
@ -184,8 +168,8 @@ public class TimiInject implements InjectFactory {
} }
} }
// 依赖注入 // 依赖注入
log.info("Running inject.."); System.out.println("Running inject..");
long injectAt = Time.now(); long injectAt = System.currentTimeMillis();
{ {
Collection<Object> objects = this.objects.values(); Collection<Object> objects = this.objects.values();
for (Object object : objects) { for (Object object : objects) {
@ -201,21 +185,14 @@ public class TimiInject implements InjectFactory {
app.afterInjectCallbackList.get(j).handler(this); app.afterInjectCallbackList.get(j).handler(this);
} }
} }
log.info("Invoking injected callback.."); System.out.println("Invoking injected callback..");
// 注入调度 // 注入调度
long invokeForInjectedAt = Time.now(); long invokeForInjectedAt = System.currentTimeMillis();
{ {
for (Map.Entry<Object, Map<Method, Integer>> item : invokeForInjected.entrySet()) { for (Map.Entry<Object, Map<Method, Integer>> item : invokeForInjected.entrySet()) {
for (Method method : item.getValue().keySet()) { for (Method method : item.getValue().keySet()) {
try { try {
long start = -1;
if (log.isDebugEnabled()) {
start = Time.now();
}
method.invoke(item.getKey()); method.invoke(item.getKey());
if (log.isDebugEnabled()) {
log.debug("invoke injected event {} ms for {}#{}", "%4s".formatted(Time.now() - start), item.getKey().getClass().getName(), method.getName());
}
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("invoke method fail: " + item.getKey().getClass().getName() + "#" + method.getName(), e); throw new RuntimeException("invoke method fail: " + item.getKey().getClass().getName() + "#" + method.getName(), e);
} }
@ -239,19 +216,19 @@ public class TimiInject implements InjectFactory {
} }
} }
long now = Time.now(); long now = System.currentTimeMillis();
log.info("Completed!"); System.out.println("Completed!");
log.info("IOC objects: " + objects.size()); System.out.println("IOC objects: " + objects.size());
log.info("Inject fields: " + fields.size()); System.out.println("Inject fields: " + fields.size());
log.info("Build Time: "); System.out.println("Build Time: ");
log.info("{} ms for Initialization", "%8s".formatted(scanAt - initAt)); System.out.println(scanAt - initAt + " ms for Initialization");
log.info("{} ms for Scan Classes", "%8s".formatted(iocAt - scanAt)); System.out.println(iocAt - scanAt + " ms for Scan Classes");
log.info("{} ms for IOC", "%8s".formatted(injectAt - iocAt)); System.out.println(injectAt - iocAt + " ms for IOC");
log.info("{} ms for Inject", "%8s".formatted(invokeForInjectedAt - injectAt)); System.out.println(invokeForInjectedAt - injectAt + " ms for Inject");
log.info("{} ms for Invoke Callback", "%8s".formatted(now - invokeForInjectedAt)); System.out.println(now - invokeForInjectedAt + " ms for Invoke Callback");
log.info("{} ms for Total", "%8s".formatted(now - initAt)); System.out.println(now - initAt + " ms for Total");
} catch (Exception e) { } catch (Exception e) {
log.error("TimiInject run error", e); e.printStackTrace();
} }
} }
@ -382,28 +359,14 @@ public class TimiInject implements InjectFactory {
* @throws IllegalAccessException 访问异常 * @throws IllegalAccessException 访问异常
*/ */
private void newInstance(IOCClass iocClass) throws Exception { private void newInstance(IOCClass iocClass) throws Exception {
long start = -1;
if (log.isDebugEnabled()) {
start = Time.now();
}
Constructor<?> constructor = iocClass.clazz.getDeclaredConstructor(); Constructor<?> constructor = iocClass.clazz.getDeclaredConstructor();
constructor.setAccessible(true); constructor.setAccessible(true);
Object object = constructor.newInstance(); Object object = constructor.newInstance();
if (TimiJava.isEmpty(iocClass.id)) { if (iocClass.id == null || iocClass.id.isEmpty() ) {
objects.put(iocClass.path, object); objects.put(iocClass.path, object);
} else { } else {
objects.put(iocClass.id, object); objects.put(iocClass.id, object);
} }
if (log.isDebugEnabled()) {
if (iocClass.isAsync) {
log.debug("IOC {} ms(async) for {}: {}", "%4s".formatted(Time.now() - start), iocClass.id, iocClass.clazz.getName());
} else {
log.debug("IOC {} ms for {}: {}", "%4s".formatted(Time.now() - start), iocClass.id, iocClass.clazz.getName());
}
}
// 控制反转方法返回 // 控制反转方法返回
objects.putAll(iocReturn(object.getClass(), object)); objects.putAll(iocReturn(object.getClass(), object));
// 收集此对象需要注入后调度的方法 // 收集此对象需要注入后调度的方法
@ -433,25 +396,16 @@ public class TimiInject implements InjectFactory {
final int j = i; final int j = i;
new Thread(() -> { new Thread(() -> {
try { try {
long start = -1;
if (log.isDebugEnabled()) {
start = Time.now();
}
Object returnObject = methods[j].invoke(object); Object returnObject = methods[j].invoke(object);
if (returnObject == null) { if (returnObject == null) {
throw new NullPointerException("return IOC object can not be null: " + clazz.getSimpleName() + "#" + methods[j].getName()); throw new NullPointerException("return IOC object can not be null: " + clazz.getSimpleName() + "#" + methods[j].getName());
} }
String id = iocReturn.value(); String id = iocReturn.value();
if (TimiJava.isEmpty(id)) { if (id == null || id.isEmpty()) {
id = returnObject.getClass().getName() + "#" + methods[j].getName(); id = returnObject.getClass().getName() + "#" + methods[j].getName();
} }
objects.put(id, returnObject); objects.put(id, returnObject);
if (log.isDebugEnabled()) {
log.debug("IOC {} ms(async) for {}: {}", "%4s".formatted(Time.now() - start), id, returnObject.getClass().getName());
}
synchronized (iocAsyncLock) { synchronized (iocAsyncLock) {
iocAsyncRunning--; iocAsyncRunning--;
if (iocAsyncRunning < 1) { if (iocAsyncRunning < 1) {
@ -462,32 +416,25 @@ public class TimiInject implements InjectFactory {
synchronized (iocAsyncLock) { synchronized (iocAsyncLock) {
iocAsyncLock.notifyAll(); iocAsyncLock.notifyAll();
} }
log.error("IOC fail class: %s#%s".formatted(clazz.getName(), methods[j].getName()), e); System.err.printf("IOC fail class: %s#%s%n", clazz.getName(), methods[j].getName());
e.printStackTrace();
} }
}).start(); }).start();
} else { } else {
long start = -1;
if (log.isDebugEnabled()) {
start = Time.now();
}
Object returnObject = methods[i].invoke(object); Object returnObject = methods[i].invoke(object);
if (returnObject == null) { if (returnObject == null) {
throw new NullPointerException("return IOC object can not be null: " + clazz.getSimpleName() + "#" + methods[i].getName()); throw new NullPointerException("return IOC object can not be null: " + clazz.getSimpleName() + "#" + methods[i].getName());
} }
String id = iocReturn.value(); String id = iocReturn.value();
if (TimiJava.isEmpty(id)) { if (id == null || id.isEmpty()) {
id = returnObject.getClass().getName() + "#" + methods[i].getName(); id = returnObject.getClass().getName() + "#" + methods[i].getName();
} }
iocObjects.put(id, returnObject); iocObjects.put(id, returnObject);
if (log.isDebugEnabled()) {
log.debug("IOC {} ms for {}: {}", "%4s".formatted(Time.now() - start), id, returnObject.getClass().getName());
}
} }
} }
} catch (InvocationTargetException | IllegalAccessException e) { } catch (InvocationTargetException | IllegalAccessException e) {
log.error("IOC fail class: %s#%s".formatted(clazz.getName(), methods[i].getName()), e); System.err.printf("IOC fail class: %s#%s%n", clazz.getName(), methods[i].getName());
e.printStackTrace();
} }
} }
return iocObjects; return iocObjects;
@ -530,10 +477,8 @@ public class TimiInject implements InjectFactory {
} else { } else {
String value = inject.value(); String value = inject.value();
// 执行注入 // 执行注入
if (TimiJava.isEmpty(value)) { if (value == null || value.isEmpty()) {
String id = fields[i].getType().getName() + "#" + fields[i].getName(); String id = fields[i].getType().getName() + "#" + fields[i].getName();
log.debug("Injecting {}", id);
Object diObject = di(id, Object.class); Object diObject = di(id, Object.class);
try { try {
if (diObject == null) { if (diObject == null) {
@ -657,9 +602,9 @@ public class TimiInject implements InjectFactory {
@Override @Override
public void ioc(String id, Object object) { public void ioc(String id, Object object) {
try { try {
log.info("Call IOC: " + id); System.out.println("Call IOC: " + id);
// ---------- 控制反转 ---------- // ---------- 控制反转 ----------
long iocAt = Time.now(); long iocAt = System.currentTimeMillis();
// 本类对象 // 本类对象
objects.put(id, object); objects.put(id, object);
// 方法返回对象 // 方法返回对象
@ -667,7 +612,7 @@ public class TimiInject implements InjectFactory {
objects.putAll(iocReturnObjects); objects.putAll(iocReturnObjects);
// ---------- 注入 ---------- // ---------- 注入 ----------
long injectAt = Time.now(); long injectAt = System.currentTimeMillis();
// 本类对象字段 // 本类对象字段
inject(object, object.getClass()); inject(object, object.getClass());
// 其他类的本类对象注入 // 其他类的本类对象注入
@ -684,14 +629,14 @@ public class TimiInject implements InjectFactory {
} }
} }
} }
long afterInjectingAt = Time.now(); long afterInjectingAt = System.currentTimeMillis();
// 一般注入后调度 // 一般注入后调度
Map<Method, Integer> methods = invokeForInjected(object.getClass()); Map<Method, Integer> methods = invokeForInjected(object.getClass());
for (Map.Entry<Method, Integer> method : methods.entrySet()) { for (Map.Entry<Method, Integer> method : methods.entrySet()) {
method.getKey().invoke(object); method.getKey().invoke(object);
} }
long callIOCListenersAt = Time.now(); long callIOCListenersAt = System.currentTimeMillis();
// 控制反转监听 // 控制反转监听
if (iocListeners.get(object.getClass()) != null) { if (iocListeners.get(object.getClass()) != null) {
List<CallbackArg<Object>> listeners = iocListeners.get(object.getClass()); List<CallbackArg<Object>> listeners = iocListeners.get(object.getClass());
@ -699,17 +644,11 @@ public class TimiInject implements InjectFactory {
listeners.get(i).handler(object); listeners.get(i).handler(object);
} }
} }
long now = Time.now(); long now = System.currentTimeMillis();
log.info("Completed for {} IOC object in {} ms", (iocReturnObjects.size() + 1), now - iocAt); System.out.printf("Completed for %s IOC object in %s ms%n", iocReturnObjects.size() + 1, now - iocAt);
log.debug("Build Time Detail: ");
log.debug("{} ms for IOC", "%8s".formatted(injectAt - iocAt));
log.debug("{} ms for Inject", "%8s".formatted(afterInjectingAt - injectAt));
log.debug("{} ms for Injected Event", "%8s".formatted(callIOCListenersAt - afterInjectingAt));
log.debug("{} ms for IOC Listener Event", "%8s".formatted(now - callIOCListenersAt));
log.debug("{} ms for Total", "%8s".formatted(now - iocAt));
} catch (Exception e) { } catch (Exception e) {
log.error("call ioc fail: " + id, e); System.err.println("call ioc fail: " + id);
e.printStackTrace();
} }
} }