Rumah > Soal Jawab > teks badan
在java spring中,是否可以动态将一个新的class加载到beanFactory中?是否可以将class类以字节流的方式存到redis中,再由类加载器重新加载到java运行实例中?
目前项目中有一个需求,需要可以动态地加载类到spring的beanFactory中或者说applicationContext里面,这个类是可以由开发人员动态上传到生产环境中,而无需重新启动生产环境。请问是否可以做到呢?还有一个问题,是否可以将class文件以字节的方式暂存在redis中间件上,需要用这个class时,动态地加载它?
PHPz2017-04-18 10:28:24
Selepas JDK1.5, terdapat API java.lang.instrument.Instrumentation siap sedia untuk melaksanakan fungsi ini.
java.lang.instrument.Instrumentation.redefineClasses(ClassDefinition... definitions)
Antara muka di atas boleh mentakrifkan semula class
sedia ada.
Gunakan seperti di bawah.
private void redefineScripts(File dir) {
File[] files = dir.listFiles();
for (File f : files) {
if (f.isDirectory()) {
redefineScripts(f);
} else if (f.getName().endsWith(".class")) {
String name = getScriptCanonicalName(f);
String path = name.replaceAll("\.", "/");
File target = new File(targetDir, path + ".class");
try {
InputStream in = new FileInputStream(target);
byte[] buf = StreamUtils.copyToByteArray(in);
ClassDefinition cdef = new ClassDefinition(scriptClassLoader.loadClass(name), buf);
instrumentation.redefineClasses(cdef);
} catch (Exception ex) {
throw new ScriptException(ex);
}
}
}
}
Kaedah untuk mendapatkan Instrumentation
objek:
private void loadAgent() {
try {
String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
VirtualMachine vm = VirtualMachine.attach(pid);
vm.loadAgent("<jar file>", OBJECT_NAME.toString());
vm.detach();
} catch (Exception ex) {
throw new RuntimeException(
"无法加载代理JAR文件["
+ Typhons.getProperty(Constants.AGENT_JAR_PATH) + "]", ex);
}
}
agent.jar
Anda perlu menentukan Agent-Class
semasa pembungkusan dan Can-Redefine-Classes
dayakan fungsi penulisan semula kelas.
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
<manifestEntries>
<Agent-Class>org.skfiy.typhon.agent.Agent</Agent-Class>
<Can-Redefine-Classes>true</Can-Redefine-Classes>
</manifestEntries>
</archive>
</configuration>
</plugin>
Agent.java
Pelaksanaan
public class Agent {
/**
* 代理主函数入口. 通过传入的{@code str }{@code ObjectName }执行其{@code setInstrumentation }
* 方法.
* <p>
* e.g.<pre>
* public void setInstrumentation(Instrumentation instrumentation) {
* this.instrumentation = instrumentation;
* }
* </pre>
*
* @param str 一个{@link ObjectName }字符串
* @param inst {@link Instrumentation }实现
* @throws Exception 异常
*/
public static void agentmain(String str, Instrumentation inst) throws Exception {
ObjectName objectName = ObjectName.getInstance(str);
MBeanServer mbeanServer = MBeanServerFactory.findMBeanServer(null).get(0);
mbeanServer.invoke(objectName, "setInstrumentation",
new Object[]{inst},
new String[]{Instrumentation.class.getName()});
}
}
Di sini saya menyuntik objek JMX
melalui Instrumentation
Mengapa saya melakukannya dengan cara ini? | .
Kemudian saya cuba memanggilnya menggunakan . vm.loadAgent();
ClassLoader
Baiklah, selagi anda mendapat objek , anda boleh melakukan apa sahaja yang anda tidak boleh lakukan sebelum ini. JMX
PHP中文网2017-04-18 10:28:24
Cuba dapatkan AutowireCapableBeanFactory melalui ApplicationContext, dan kemudian panggil kaedah createBean() atau autowire() untuk menyuntik
怪我咯2017-04-18 10:28:24
Java mempunyai aliran input dan output objek, jadi anda pasti boleh menyimpan objek dalam bait
阿神2017-04-18 10:28:24
Semua yang dinyatakan di atas adalah salah. Saya boleh memberitahu anda dengan jelas bahawa segala-galanya mungkin.