浏览 2968 次
锁定老帖子 主题:Java自动生成Spring配置文件
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2011-07-01
其实使用annotation是不错的选择,但是annotation分布在系统代码之中不利于管理. 所以现在流行使用最多的,还是xml方式。 但是使用Spring的xml配置实在是麻烦,而且还容易把包名,类名写错。 于是我想:"能不能自已动生成Spring的配置文件"; 说明一下:我一直相信代码的自动构建比“人工敲代码”更可靠 凭着这个想法,实现如下: package org.frame.base.unit; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.net.URL; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import org.frame.base.web.controller.BaseController; import org.springframework.aop.ClassFilter; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.xml.DomDriver; /** * 自动构建bean配置文件 提供包名,自动生成该包以下的Bean配置文件内容.[包含子包] * 1. BaseController 如果为这个类的实例,自动生成parent * * @author yangchunlong.tw * */ public class GeneratorBean { private static final String PROTOCOL_FILE = "file"; private static final String CLASS_FILE = ".class"; private static final String BASE_CONTROLLER = "baseController"; private final String packageName; private final ClassFilter filter;// 可以没有classFilter private final String header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE beans PUBLIC \"-//SPRING//DTD BEAN//EN\" \" http://www.springframework.org/dtd/spring-beans.dtd \">\n"; public GeneratorBean(String packageName) { this(packageName, null); } public GeneratorBean(String packageName, ClassFilter filter) { this.packageName = packageName; this.filter = filter; } /** * 生成配置串 * @return * @throws IOException */ @SuppressWarnings("unchecked") public String buildSpringBean() throws IOException { List<Class<?>> clazzs = scannerPackage(); StringBuffer sb = new StringBuffer(header); for (Class clazz : clazzs) { try { if(BaseController.class.isInstance(clazz.newInstance())){ sb.append(" <bean class=\"").append(clazz.getName()).append("\"").append(" parent=\"").append(BASE_CONTROLLER).append("\" ") .append(" />").append("\n"); }else{ sb.append(" <bean class=\"").append(clazz.getName()).append("\"") .append(" />").append("\n"); } } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return sb.toString(); } /** * 生成配置文件 * @throws IOException */ public void buildSpringXML(String fileName){ String base = System.getProperty("user.dir"); FileOutputStream os = null; OutputStreamWriter writer = null; try { os = new FileOutputStream(base+"/"+fileName); writer = new OutputStreamWriter(os,Charset.forName("UTF-8")); XStream xStream = new XStream(new DomDriver());// 不需要XPP3库 xStream.alias("beans", Beans.class); xStream.alias("bean", Bean.class); xStream.useAttributeFor(String.class); xStream.aliasField("default-autowire", Beans.class, "default_autowire"); xStream.aliasField("class", Bean.class, "_class"); Beans beans = new Beans(); List<Class<?>> clazzs = scannerPackage(); for (Class clazz : clazzs) { Bean bean = new Bean(); try { if(BaseController.class.isInstance(clazz.newInstance())){ bean.set_class(clazz.getName()); bean.setParent(BASE_CONTROLLER); }else{ bean.set_class(clazz.getName()); } } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } beans.addBean(bean); } writer.write(header); xStream.toXML(beans, writer); } catch (FileNotFoundException e1) { e1.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ // IOUtils.copy(reader, writer); try { os.close(); writer.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 遍历文件夹下的所有类 * * @param packageName * @return * @throws IOException */ public List<Class<?>> scannerPackage() throws IOException { List<Class<?>> list = new ArrayList<Class<?>>(); Enumeration<URL> en = getClass().getClassLoader().getResources( dotToPath(packageName)); while (en.hasMoreElements()) { URL url = en.nextElement(); if (PROTOCOL_FILE.equals(url.getProtocol())) { EncodingUtils parse = new EncodingUtils(); String fileName = parse.decodeURL(url.getFile(), "UTF-8"); File root = new File(fileName); findInDirectory(list, root, root, packageName); } } return list; } private void findInDirectory(List<Class<?>> results, File rootDir, File dir, String packageName) { File[] files = dir.listFiles(); String rootPath = rootDir.getPath(); for (File file : files) { if (file.isFile()) { String classFileName = file.getPath(); if (classFileName.endsWith(CLASS_FILE)) { String className = classFileName.substring(rootPath .length() - packageName.length(), classFileName.length() - CLASS_FILE.length()); add(results, pathToDot(className)); } } else if (file.isDirectory()) { findInDirectory(results, rootDir, file, packageName); } } } /** * 添加 某个类名到某架包中 此类必须匹配ClassFilter.[] * * @param results * @param className */ private void add(List<Class<?>> results, String className) { Class<?> clazz = null; try { clazz = Class.forName(className); } catch (ClassNotFoundException e) { // 架包中会有些类会加载不到. System.out.println("加载类失败:" + className); return; } if (filter == null || filter.matches(clazz)) results.add(clazz); } /** * 转包名为路径[. ==> /] * * @param s * @return */ private String dotToPath(String s) { return s.replace('.', '/'); } /** * 转路径为包名[/ ==> .]/[\\ ==> .] * * @param s * @return */ private String pathToDot(String s) { return s.replace('/', '.').replace('\\', '.'); } } 以上是实现代码,主要是使用字符串拼凑来实现xml的输出和xstream的面向对象方式来序列化XML,我还是比较喜欢xstream,还可以把xml反序列化为Java对象. 测试代码如下: package com.frame.base.unit; import java.io.IOException; import org.frame.base.unit.GeneratorBean; import org.springframework.aop.ClassFilter; import org.springframework.web.servlet.mvc.Controller; /** * 可以自动生成Controler的实例才生成配置文件 * @author yangchunlong.tw * */ public class TestGeneratorBean { /** * 不需要自动生成的Controller */ static String[] exps = new String[]{ "handing.beanName.IndexSpringController" }; /** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { // TODO Auto-generated method stub GeneratorBean gg = new GeneratorBean("handing",new ClassFilter(){ @Override public boolean matches(Class clazz) { try { if(Controller.class.isInstance(clazz.newInstance())){ for(String exp:exps){ if(exp.equals(clazz.getName())){ return false; } } return true; }else{ return false; } } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } return false; } }); System.out.println(gg.buildSpringBean()); System.out.println(System.getProperty("user.dir")); gg.buildSpringXML("beans2.xml"); } } 这里定义了自动构建的过程,比如,我可以把包名handing以下的类生成bean, 这里定义了规则; 1. 此类必须为Controller的实例类。 2. 此类不在exps 的列表里面 可能有些类不需要生成配置,在这里可以配置。 当然规则是自定义的,我在自动构建的代码里面,也使用了规则,比如实例为"BaseController"的生成parent参数,如果不是的,只需要生成普通的bean. 以下是xstream的实例类: package org.frame.base.unit; import java.util.ArrayList; import java.util.List; /** * <beans default-autowire=\"byName\"> * ... * <bean .../> * </beans> * @author yangchunlong.tw * */ public class Beans { /** * 自动构建方式:默认byName[default_autowire == > default-autowire] */ private String default_autowire = "byName"; /** * Spring的bean. */ List<Bean> beans = new ArrayList<Bean>(); public String getDefault_autowire() { return default_autowire; } public void setDefault_autowire(String default_autowire) { this.default_autowire = default_autowire; } public List<Bean> getBeans() { return beans; } public void setBeans(List<Bean> beans) { this.beans = beans; } public void addBean(Bean bean){ beans.add(bean); } } package org.frame.base.unit; public class Bean { /** * bean_类包名[_class == > class] */ private String _class; /** * bean_父bean */ private String parent; public String get_class() { return _class; } public void set_class(String _class) { this._class = _class; } public String getParent() { return parent; } public void setParent(String parent) { this.parent = parent; } } 使用xstream扩展起来比较方便,比如,如果你使用的是CustomSpring扩展的Application.那么使用自己扩展的属性将是相当犀利的哦。 最后输出xml的结构如下: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" " http://www.springframework.org/dtd/spring-beans.dtd "> <beans default-autowire="byName"> <bean class="handing.beanName.screen.home.HomeAuto"/> <bean class="handing.beanName.screen.home.AdminAuto" parent="baseController"/> <bean class="handing.beanName.screen.IndexAuto"/> <bean class="handing.beanName.IndexController"/> <bean class="handing.beanName.IndexAdminController"/> </beans> 这可是相当标准的xml哦,直接复制到运行目标就可以了. 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-07-12
楼主试试Maven的Archetype呢
|
|
返回顶楼 | |