onEnable 之前加载插件
修复 NoClassDefFoundError 的问题
This commit is contained in:
		@@ -14,7 +14,8 @@ import java.io.File;
 | 
			
		||||
import java.lang.reflect.Field;
 | 
			
		||||
 | 
			
		||||
@Dependency(type = Dependency.Type.LIBRARY, maven = "org.ow2.asm:asm:6.1.1")
 | 
			
		||||
@Dependency(type = Dependency.Type.LIBRARY, maven = "com.zaxxer:HikariCP:3.0.0")
 | 
			
		||||
@Dependency(type = Dependency.Type.LIBRARY, maven = "com.zaxxer:HikariCP:3.1.0")
 | 
			
		||||
@Dependency(type = Dependency.Type.LIBRARY, maven = "org.slf4j:slf4j-api:1.7.25")
 | 
			
		||||
public class TLib {
 | 
			
		||||
 | 
			
		||||
    private static TLib tLib;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,7 @@
 | 
			
		||||
package com.ilummc.tlib.annotations;
 | 
			
		||||
 | 
			
		||||
import com.ilummc.tlib.util.Ref;
 | 
			
		||||
 | 
			
		||||
import java.lang.annotation.ElementType;
 | 
			
		||||
import java.lang.annotation.Retention;
 | 
			
		||||
import java.lang.annotation.RetentionPolicy;
 | 
			
		||||
@@ -20,6 +22,6 @@ public @interface Config {
 | 
			
		||||
 | 
			
		||||
    boolean listenChanges() default false;
 | 
			
		||||
 | 
			
		||||
    int excludeModifiers() default Modifier.STATIC | Modifier.TRANSIENT;
 | 
			
		||||
    int excludeModifiers() default Modifier.STATIC | Modifier.TRANSIENT | Ref.ACC_SYNTHETIC | Ref.ACC_BRIDGE;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@ package com.ilummc.tlib.inject;
 | 
			
		||||
import com.ilummc.tlib.TLib;
 | 
			
		||||
import com.ilummc.tlib.annotations.*;
 | 
			
		||||
import com.ilummc.tlib.dependency.TDependency;
 | 
			
		||||
import com.ilummc.tlib.util.Ref;
 | 
			
		||||
import com.ilummc.tlib.util.TLogger;
 | 
			
		||||
import org.bukkit.Bukkit;
 | 
			
		||||
import org.bukkit.plugin.Plugin;
 | 
			
		||||
@@ -14,22 +15,10 @@ import java.lang.reflect.Field;
 | 
			
		||||
public class DependencyInjector {
 | 
			
		||||
 | 
			
		||||
    public static void inject(Plugin plugin, Object o) {
 | 
			
		||||
        try {
 | 
			
		||||
            injectLogger(plugin, o);
 | 
			
		||||
        } catch (NoClassDefFoundError ignored) {
 | 
			
		||||
        }
 | 
			
		||||
        try {
 | 
			
		||||
            injectConfig(plugin, o);
 | 
			
		||||
        } catch (NoClassDefFoundError ignored) {
 | 
			
		||||
        }
 | 
			
		||||
        try {
 | 
			
		||||
            injectPluginInstance(plugin, o);
 | 
			
		||||
        } catch (NoClassDefFoundError ignored) {
 | 
			
		||||
        }
 | 
			
		||||
        try {
 | 
			
		||||
            injectDependencies(plugin, o);
 | 
			
		||||
        } catch (NoClassDefFoundError ignored) {
 | 
			
		||||
        }
 | 
			
		||||
        injectLogger(plugin, o);
 | 
			
		||||
        injectConfig(plugin, o);
 | 
			
		||||
        injectPluginInstance(plugin, o);
 | 
			
		||||
        injectDependencies(plugin, o);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static void injectOnEnable(Plugin plugin) {
 | 
			
		||||
@@ -48,7 +37,7 @@ public class DependencyInjector {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void ejectConfig(Plugin plugin, Object o) {
 | 
			
		||||
        for (Field field : o.getClass().getDeclaredFields()) {
 | 
			
		||||
        for (Field field : Ref.getDeclaredFields(o.getClass())) {
 | 
			
		||||
            Config config;
 | 
			
		||||
            if ((config = field.getType().getAnnotation(Config.class)) != null) {
 | 
			
		||||
                try {
 | 
			
		||||
@@ -64,7 +53,7 @@ public class DependencyInjector {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void injectConfig(Plugin plugin, Object o) {
 | 
			
		||||
        for (Field field : o.getClass().getDeclaredFields()) {
 | 
			
		||||
        for (Field field : Ref.getDeclaredFields(o.getClass())) {
 | 
			
		||||
            try {
 | 
			
		||||
                Config config;
 | 
			
		||||
                if ((config = field.getType().getAnnotation(Config.class)) != null) {
 | 
			
		||||
@@ -100,7 +89,7 @@ public class DependencyInjector {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void injectLogger(Plugin plugin, Object o) {
 | 
			
		||||
        for (Field field : o.getClass().getDeclaredFields()) {
 | 
			
		||||
        for (Field field : Ref.getDeclaredFields(o.getClass())) {
 | 
			
		||||
            try {
 | 
			
		||||
                Logger logger;
 | 
			
		||||
                if ((logger = field.getAnnotation(Logger.class)) != null) {
 | 
			
		||||
@@ -116,7 +105,7 @@ public class DependencyInjector {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void injectPluginInstance(Plugin plugin, Object o) {
 | 
			
		||||
        for (Field field : o.getClass().getDeclaredFields()) {
 | 
			
		||||
        for (Field field : Ref.getDeclaredFields(o.getClass())) {
 | 
			
		||||
            try {
 | 
			
		||||
                PluginInstance instance;
 | 
			
		||||
                if ((instance = field.getAnnotation(PluginInstance.class)) != null) {
 | 
			
		||||
 
 | 
			
		||||
@@ -49,9 +49,7 @@ public class TLibPluginManager implements PluginManager {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Plugin loadPlugin(File file) throws InvalidPluginException, InvalidDescriptionException, UnknownDependencyException {
 | 
			
		||||
        Plugin plugin = instance.loadPlugin(file);
 | 
			
		||||
        DependencyInjector.injectOnEnable(plugin);
 | 
			
		||||
        return plugin;
 | 
			
		||||
        return instance.loadPlugin(file);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
@@ -94,6 +92,7 @@ public class TLibPluginManager implements PluginManager {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void enablePlugin(Plugin plugin) {
 | 
			
		||||
        DependencyInjector.injectOnEnable(plugin);
 | 
			
		||||
        instance.enablePlugin(plugin);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										18
									
								
								src/main/java/com/ilummc/tlib/util/IO.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/main/java/com/ilummc/tlib/util/IO.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
package com.ilummc.tlib.util;
 | 
			
		||||
 | 
			
		||||
import java.io.ByteArrayOutputStream;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
 | 
			
		||||
public class IO {
 | 
			
		||||
 | 
			
		||||
    public static byte[] readFully(InputStream inputStream) throws IOException {
 | 
			
		||||
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
 | 
			
		||||
        byte[] buf = new byte[1024];
 | 
			
		||||
        int len = 0;
 | 
			
		||||
        while ((len = inputStream.read(buf)) > 0) {
 | 
			
		||||
            stream.write(buf, 0, len);
 | 
			
		||||
        }
 | 
			
		||||
        return stream.toByteArray();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										59
									
								
								src/main/java/com/ilummc/tlib/util/Ref.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/main/java/com/ilummc/tlib/util/Ref.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
			
		||||
package com.ilummc.tlib.util;
 | 
			
		||||
 | 
			
		||||
import com.ilummc.tlib.util.asm.AsmAnalyser;
 | 
			
		||||
import org.objectweb.asm.ClassReader;
 | 
			
		||||
import org.objectweb.asm.ClassWriter;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.concurrent.ThreadSafe;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.lang.reflect.Field;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.Objects;
 | 
			
		||||
import java.util.concurrent.ConcurrentHashMap;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
@ThreadSafe
 | 
			
		||||
public class Ref {
 | 
			
		||||
 | 
			
		||||
    private static final Map<String, List<Field>> cachedFields = new ConcurrentHashMap<>();
 | 
			
		||||
 | 
			
		||||
    public static final int ACC_BRIDGE = 0x0040;
 | 
			
		||||
    public static final int ACC_SYNTHETIC = 0x1000;
 | 
			
		||||
 | 
			
		||||
    public static List<Field> getDeclaredFields(Class<?> clazz) {
 | 
			
		||||
        return getDeclaredFields(clazz, 0, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static List<Field> getDeclaredFields(String clazz, int excludeModifiers, boolean cache) {
 | 
			
		||||
        try {
 | 
			
		||||
            return getDeclaredFields(Class.forName(clazz), excludeModifiers, cache);
 | 
			
		||||
        } catch (ClassNotFoundException e) {
 | 
			
		||||
            return Collections.emptyList();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static List<Field> getDeclaredFields(Class<?> clazz, int excludeModifiers, boolean cache) {
 | 
			
		||||
        try {
 | 
			
		||||
            Class.forName("org.objectweb.asm.ClassVisitor");
 | 
			
		||||
            List<Field> fields;
 | 
			
		||||
            if ((fields = cachedFields.get(clazz.getName())) != null) return fields;
 | 
			
		||||
            ClassReader classReader = new ClassReader(clazz.getResourceAsStream("/" + clazz.getName().replace('.', '/') + ".class"));
 | 
			
		||||
            AsmAnalyser analyser = new AsmAnalyser(new ClassWriter(ClassWriter.COMPUTE_MAXS), excludeModifiers);
 | 
			
		||||
            classReader.accept(analyser, ClassReader.SKIP_DEBUG);
 | 
			
		||||
            fields = analyser.getFields().stream().map(name -> {
 | 
			
		||||
                try {
 | 
			
		||||
                    return clazz.getDeclaredField(name);
 | 
			
		||||
                } catch (Throwable ignored) {
 | 
			
		||||
                }
 | 
			
		||||
                return null;
 | 
			
		||||
            }).filter(Objects::nonNull).collect(Collectors.toList());
 | 
			
		||||
            if (cache) cachedFields.putIfAbsent(clazz.getName(), fields);
 | 
			
		||||
            return fields;
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            return Collections.emptyList();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										31
									
								
								src/main/java/com/ilummc/tlib/util/asm/AsmAnalyser.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/main/java/com/ilummc/tlib/util/asm/AsmAnalyser.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
package com.ilummc.tlib.util.asm;
 | 
			
		||||
 | 
			
		||||
import org.objectweb.asm.ClassVisitor;
 | 
			
		||||
import org.objectweb.asm.FieldVisitor;
 | 
			
		||||
import org.objectweb.asm.Opcodes;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
public class AsmAnalyser extends ClassVisitor implements Opcodes {
 | 
			
		||||
 | 
			
		||||
    private final List<String> fields = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
    private final int excludeModifier;
 | 
			
		||||
 | 
			
		||||
    public AsmAnalyser(ClassVisitor classVisitor, int excludeModifiers) {
 | 
			
		||||
        super(Opcodes.ASM6, classVisitor);
 | 
			
		||||
        this.excludeModifier = excludeModifiers;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
 | 
			
		||||
        if ((access & excludeModifier) == 0)
 | 
			
		||||
            fields.add(name);
 | 
			
		||||
        return super.visitField(access, name, descriptor, signature, value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public List<String> getFields() {
 | 
			
		||||
        return fields;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -51,21 +51,6 @@ import java.util.Random;
 | 
			
		||||
@SuppressWarnings("deprecation")
 | 
			
		||||
public class Main extends JavaPlugin implements Listener {
 | 
			
		||||
 | 
			
		||||
    public Main() {
 | 
			
		||||
        super();
 | 
			
		||||
 | 
			
		||||
        inst = this;
 | 
			
		||||
        disable = false;
 | 
			
		||||
 | 
			
		||||
        TLib.injectPluginManager();
 | 
			
		||||
 | 
			
		||||
        // 载入配置
 | 
			
		||||
        saveDefaultConfig();
 | 
			
		||||
 | 
			
		||||
        // 加载依赖
 | 
			
		||||
        TLib.init();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Getter
 | 
			
		||||
    private static Plugin inst;
 | 
			
		||||
    @Getter
 | 
			
		||||
@@ -116,6 +101,17 @@ public class Main extends JavaPlugin implements Listener {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onLoad() {
 | 
			
		||||
        inst = this;
 | 
			
		||||
        disable = false;
 | 
			
		||||
 | 
			
		||||
        TLib.injectPluginManager();
 | 
			
		||||
 | 
			
		||||
        // 载入配置
 | 
			
		||||
        saveDefaultConfig();
 | 
			
		||||
 | 
			
		||||
        // 加载依赖
 | 
			
		||||
        TLib.init();
 | 
			
		||||
 | 
			
		||||
        // 载入目录
 | 
			
		||||
        setupDataFolder();
 | 
			
		||||
        // 注册配置
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user