昨天在编写代码生成器时遇到一个问题:用JET2模板引擎不能够动态编译代码模板文件,也就意味着我不能都动态的添加自定义代码模板,这和我希望的开放式式的代码生成器不符合。我最看中的就是jet2模板里能由模板编写者自己控制生成哪些代码文件,很开发灵活。如果放弃jet2的话我还没找到更好的代替者,所以我只能想方设法使代码生成器能动态加载用户添加的模板。想到的办法是:让用户编写好代码模板后,将模板文件和编译好的模板类一起打包成jar,然后由代码生成运行时动态加载。
插件动态加载jar方法:自定义类加载器继承URLClassLoader,重写addURl方法使之变为public,方便多次添加jar。
代码:
public class DynamicClassLoader extends URLClassLoader {
/**
* 类加载器实例化后,再添加单个jar
*/
@Override
public void addURL(URL url) {
super.addURL(url);
}
static final URL[] EMPTY_URLS = new URL[]{};
public DynamicClassLoader(){
super(EMPTY_URLS);
}
public DynamicClassLoader(URL[] urls){
super(urls ,(Thread.currentThread().getContextClassLoader() == null ||
Thread.currentThread().getContextClassLoader() == ClassLoader.getSystemClassLoader())?
Compiler.class.getClassLoader():Thread.currentThread().getContextClassLoader());
}
public DynamicClassLoader(ClassLoader parent){
super(EMPTY_URLS,parent);
}
/**
* 创建类加载器
* @param urls 待加载的jarUrl集合
* @param parent 父类加载器
*/
public DynamicClassLoader(URL[] urls, ClassLoader parent){
super(urls,parent);
}
}
在需要的地方实例化调用(如插件启动时实例化),调用代码如下:
代码:
/**
* 动态加载指定jar
* @param jarURL
*/
public void loadJar(File jar){
if(jar != null){
try {
dynamicClassLoader.addURL(jar.toURI().toURL());
} catch (MalformedURLException e) {
LogUtil.logError(e.getMessage(),e);
}
setPathToTemplateClassMapByJar(jar);
}
}
/**
* 根据模板jar文件设置代码模板路径和类映射集合
* @param jar 模板jar文件,必须包含模板源码和编译后的模板类
*/
public void setPathToTemplateClassMapByJar(File jar){
if(jar == null){
return;
}
try {
JarFile jf = new JarFile(jar);
final Enumeration<JarEntry> entries = jf.entries();
//保存所有模板源文件
List<String> templatePathList = new ArrayList<String>();
//保存编译的模板类名和类全路径映射集合
Map<String, String> classMap = new HashMap<String, String>();
while (entries.hasMoreElements()) {
final JarEntry entry = entries.nextElement();
final String entryName = entry.getName();
if (entryName.startsWith("templates")) {
templatePathList.add(entryName);
}else if(entryName.endsWith(".class")){
int lastspindex = entryName.lastIndexOf("/");
String key = entryName.substring(lastspindex + 1, entryName.length() - 6);
String className = entryName.substring(0, entryName.length() - 6).replace("/", ".");
classMap.put(key, className);
}
}
for(String templatePath : templatePathList){
int lastspindex = templatePath.lastIndexOf("/");
int lastpoindex = templatePath.lastIndexOf(".");
String key = "_jet_"+templatePath.substring(lastspindex + 1, lastpoindex).replace(".", "");
String className = classMap.get(key);
if(className != null){
pathToTemplateClassMap.put(templatePath, className);
}
}
} catch (IOException e) {
LogUtil.logError(e.getMessage(),e);
}
}
还要修改代码生成器插件的jet2扩展中的模板加载器类,使之能根据模板路径用自定义类加载器来实例化模板对象。
代码如下:
/**
* 自定义模板加载器
* CreatorTemplateLoader
*/
public class CreatorTemplateLoader implements JET2TemplateLoader,
JET2TemplateLoaderExtension {
private JET2TemplateLoader delegate = null;
/*
* (non-Javadoc)
*
* @see org.eclipse.jet.JET2TemplateLoader#getTemplate(java.lang.String)
*/
public JET2Template getTemplate(final String templatePath) {
final String ordinal = CodeGenActivator.pathToTemplateClassMap.get(templatePath);
if(ordinal != null) {
try {
return (JET2Template)CodeGenActivator.getDefault().getDynamicClassLoader().loadClass(ordinal).newInstance();
} catch (InstantiationException e) {
LogUtil.logError(e.getMessage(), e);
} catch (IllegalAccessException e) {
LogUtil.logError(e.getMessage(), e);
} catch (ClassNotFoundException e) {
LogUtil.logError(e.getMessage(), e);
}
}
return this.delegate != null ? this.delegate.getTemplate(templatePath) : null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jet.JET2TemplateLoaderExtension#getDelegateLoader()
*/
public JET2TemplateLoader getDelegateLoader() {
return this.delegate;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jet.JET2TemplateLoaderExtension#setDelegateLoader(org.eclipse
* .jet.JET2TemplateLoader)
*/
public void setDelegateLoader(final JET2TemplateLoader loader) {
this.delegate = loader;
}
}
隔了好久才记起这个文章没写完,今天记起后赶紧补充完整了。
分享到:
相关推荐
动态加载jar包是一种在程序运行时按需引入外部库或者组件的技术,这使得应用程序更加灵活,可以适应不同的环境和需求。这种技术广泛应用于插件系统、框架开发以及服务升级等场景,因为它允许程序在不重启的情况下...
在Java编程语言中,动态加载jar包是一种常见的需求,它允许程序在运行时根据需要加载新的功能或更新现有的模块,增强了软件的灵活性和可扩展性。动态加载jar包技术主要涉及Java的反射机制、类加载器和插件系统。下面...
在Java编程语言中,动态加载jar文件是一种关键的特性,它允许程序在运行时加载新的类库或组件,而不是在编译时静态地链接。这种技术对于实现插件式开发或者模块化系统至关重要,因为它提供了灵活性和可扩展性。下面...
在Android开发中,动态加载JAR(Java Archive)文件是一种常见的技术,它允许应用程序在运行时加载和执行不在原始APK文件中的代码。这种技术有多种应用场景,例如更新功能、热修复、插件化框架等。下面将详细介绍...
总之,jarjar-1.4.jar是解决Java开发中jar包冲突问题的一个有效工具。通过合理使用规则文件,我们可以对jar包进行定制化处理,从而更好地管理和优化我们的项目。在实践中,不断探索和学习jarjar的用法,能够帮助我们...
在Java编程中,动态加载JAR或ZIP包是一项重要的技术,它允许程序在运行时根据需求加载外部库,而不是在编译时静态地链接。这种技术对于实现插件化、模块化系统,或者处理频繁更新的组件非常有用。下面将详细讲解如何...
"restclient-ui-3.2.2-jar-with-dependencies" 是这个工具的一个特定版本,该版本包含了所有必要的依赖项,使得用户可以直接运行而无需额外安装其他库。这个版本号表明它是RESTClient的3.2.2迭代,且“jar-with-...
ksoap2-android-assembly-2.6.5-jar-with-dependencies.jar 要是需要最新的,下载地址: http://code.google.com/p/ksoap2-android/
在热加载场景下,JarinJAR使得在运行时能够动态替换内部的JAR,达到更新代码的目的。然而,JarinJAR并不直接支持热加载,需要配合类加载器的定制工作。 **动态编译**:在热加载过程中,可能会涉及到对源代码的动态...
Spring bean 一般通过配置文件和注解进行加载,如果要实现jar或class...测试示例中是spring boot 的部分代码,动态加载的内容为接口实现类,且初始化时加载本地的实现类,动态加载后改为非程序加载目录中的jar实现类。
这个问题通常发生在使用`Class.forName()`或`ClassLoader.getSystemClassLoader().loadClass()`尝试动态加载第三方JAR中的类时。 Java虚拟机(JVM)的类加载机制是导致此问题的关键。自JDK 1.2以来,JVM采用委托...
在Android开发中,有时我们需要实现动态加载功能,例如在运行时添加或更新功能模块,而无需重新编译和发布整个应用程序。这就是动态加载jar文件的作用。动态加载不仅可以提高应用程序的灵活性,还可以降低更新成本,...
`agent-jar-2.2.1.jar`正是这样一个代理库,它可能是为了方便在运行时对Java应用进行监控、性能分析或者增强功能而设计的。 `agent-jar-2.2.1.jar`的版本号为2.2.1,这表明它是经过了多次迭代和改进的稳定版本。...
标题中的"coherence.jar-coherence-work.jar-tangosol.jar-"揭示了这是一组与Oracle Coherence相关的Java库文件。Coherence是Oracle公司提供的一种分布式数据管理解决方案,它主要用于实现高性能的数据缓存、数据...
在Android系统中,插件化开发是一种常见的技术,它允许应用程序在运行时动态加载和执行新的功能模块,而无需重新编译或安装整个应用。这种技术对于大型应用或需要频繁更新功能的应用尤其有价值,因为它降低了维护...
在Android开发中,动态加载JAR文件是一种常见的技术,它允许程序在运行时加载和执行新的功能或服务,而无需重新编译和安装整个应用程序。这样的设计极大地提高了灵活性,使得应用能够实现模块化,便于更新和维护。...
在Java编程中,有时我们需要动态地加载外部JAR文件,并执行其中特定的类方法,这在插件系统、模块化应用或动态扩展性需求中尤为常见。本篇将详细讲解如何实现这一目标。 首先,理解JAR(Java Archive)文件是Java...
当你遇到“找不到javax.servlet.*”这样的错误时,通常是因为你的项目缺少了这个库,所以需要引入`javax.servlet.jar`来解决问题。 1. **Java Servlet简介** Java Servlet是Java平台上的一个标准,用于扩展服务器...
总的来说,dex2jar-2.1是Android逆向工程中的一个重要工具,它的出现解决了旧版本在处理特定Dex文件时的局限性,提高了开发者和安全研究人员的工作效率。了解并熟练掌握它的使用方法,能帮助我们更好地探索和理解...
动态加载Apk主要应用于插件化开发,允许程序在运行时添加或更新功能模块。以下是一些关键步骤: 1. **创建自定义ClassLoader**:你需要继承dalvik.system.DexClassLoader或者dalvik.system.PathClassLoader,重写其...