锁定老帖子 主题:零配置Service
精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-09-14
2.前提:约定大于配置, Service配置有规则可循 3.实现方式: 在Spring初始化时生成Service XML 配置文件,加载到初始化过程中 4.代码 1.MyXmlWebApplicationContext.java /** * */ package service.utils; import java.io.File; import java.io.IOException; import java.io.StringWriter; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.Result; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.WordUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.core.io.ByteArrayResource; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.PropertiesLoaderUtils; import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.core.type.classreading.CachingMetadataReaderFactory; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.util.ClassUtils; import org.springframework.util.ResourceUtils; import org.springframework.util.xml.DomUtils; import org.springframework.web.context.support.XmlWebApplicationContext; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * @author yangjk * @since 2009-9-13 */ public class MyXmlWebApplicationContext extends XmlWebApplicationContext { private static Log LOG = LogFactory.getLog(MyXmlWebApplicationContext.class); private Properties getProperties() { try { return PropertiesLoaderUtils.loadAllProperties("config.properties"); } catch (IOException e) { LOG.error("读取config.properties失败."); throw new RuntimeException(e); } } public byte[] getGenServiceInputStream() { Properties prop = getProperties(); String path = prop.getProperty("service.path"); String pkg = prop.getProperty("service.package"); try { File file = ResourceUtils.getFile("classpath:" + path); Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(file); List list = DomUtils.getChildElementsByTagName(doc.getDocumentElement(), "bean"); Map map = new HashMap(); for (int i = 0; i < list.size(); i++) { Element ele = (Element) list.get(i); map.put(ele.getAttribute("id"), ele.getAttribute("class")); } Map genMap = this.getPackageService(pkg); for (Iterator iterator = genMap.entrySet().iterator(); iterator.hasNext();) { Map.Entry entry = (Map.Entry) iterator.next(); String id = (String)entry.getKey(); String clazz = (String)entry.getValue(); if(map.get(id) == null) { Element comm = doc.createElement("bean"); comm.setAttribute("id", id); comm.setAttribute("class", clazz); doc.getDocumentElement().appendChild(comm); if (LOG.isDebugEnabled()) { LOG.info("Service Gen XML :" + id +" -> " + clazz); } } } DOMSource ds = new DOMSource(doc); Transformer transformer = TransformerFactory.newInstance().newTransformer(); StringWriter writer = new StringWriter(); Result result = new StreamResult(writer); transformer.transform(ds, result); return writer.toString().getBytes(); } catch (Exception e) { e.printStackTrace(); } return null ; } private static final String RESOURCE_PATTERN = "**/*.class"; private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); public Map getPackageService(String pkg) { Map map = new HashMap(); String[] pkgs = pkg.split(","); try { for (int i = 0; i < pkgs.length; i++) { String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + ClassUtils.convertClassNameToResourcePath(pkgs[i]) + RESOURCE_PATTERN; Resource[] resources; resources = this.resourcePatternResolver.getResources(pattern); MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver); for (Resource resource : resources) { if (resource.isReadable()) { MetadataReader reader = readerFactory.getMetadataReader(resource); String className = reader.getClassMetadata().getClassName(); String beanId = getBeanId(className); if (beanId != null) { map.put(beanId, className); } } } } } catch (IOException e) { e.printStackTrace(); throw new RuntimeException( "Failed to scan classpath for unlisted classes", e); } return map; } //约定 private String getBeanId(String className) { if(StringUtils.isNotBlank(className) && className.indexOf('$') == -1) { String simpleName = StringUtils.substringAfterLast(className, "."); if(simpleName.endsWith("Impl")) { simpleName = simpleName.substring(0, simpleName.length()-"Impl".length()); } simpleName = WordUtils.uncapitalize(simpleName); return simpleName ; } return null ; } protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) { Resource resource2 = new ByteArrayResource(this.getGenServiceInputStream()); reader.loadBeanDefinitions(resource2); } } 2.config.properties #spring service xml path service.path=conf/service.xml #spring service package service.package=service.impl 3.service.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <!-- add your service here --> </beans> 4.web.xml <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/classes/conf/dataAccessContext-local.xml /WEB-INF/classes/conf/applicationContext.xml /WEB-INF/classes/conf/controller.xml </param-value> </context-param> <context-param> <param-name>contextClass</param-name> <param-value>service.utils.MyXmlWebApplicationContext</param-value> </context-param> 5.按照规则可以随意扩展 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-09-15
thinkinperson 写道 请问有这个需要吗?能在什么场景中用这个呢?annocation不好吗?
如果按你的设计。一个接口。两个实现类。你怎么能判断到底是使用了哪个实现类呢? jdk1.4没有Annotation ,写Annotation有时候觉得多余,能不写就不写 一个接口2个实现类的情况你可以在service.xml 按照getBeanId方法的规则为这个bean取个ID配置,在MyXmlWebApplicationContext.java不会覆盖有这个Id的配置. |
|
返回顶楼 | |
发表时间:2009-09-15
一个接口。两个实现类。2个实现类的名称一般是不一样的, 会生成2个ID不一样的bean,
按照id去用就行了, 如果是不同package中的名称一样的实现类,按照上面的方法去做就行了. |
|
返回顶楼 | |
发表时间:2009-09-17
何苦咧~~~
|
|
返回顶楼 | |
发表时间:2009-09-18
satanest 写道 何苦咧~~~ yy 呀. |
|
返回顶楼 | |
发表时间:2009-09-23
还是应用annotation的方式比较好,语言不可能太智能
|
|
返回顶楼 | |
发表时间:2009-09-23
各有所好么.
|
|
返回顶楼 | |
发表时间:2009-09-27
支持楼主的 service 零配置方案,可节省大量配置,维护工作 。 现在敏捷设计都趋向 约定大于配置 (CBC).
到处写 Annotation ,本质还是一种配置,而且分散到了类中,这种用法我一直觉得很恶心,对于大型系统,维护难度非常大,很不明智。 “语言不可能太智能”,这句话没错,所以,在包,类命名上尽量遵循 CBC 原则,以减少无聊的机械劳动。 |
|
返回顶楼 | |
发表时间:2009-09-27
raymond2006k 写道 支持楼主的 service 零配置方案,可节省大量配置,维护工作 。 现在敏捷设计都趋向 约定大于配置 (CBC). 到处写 Annotation ,本质还是一种配置,而且分散到了类中,这种用法我一直觉得很恶心,对于大型系统,维护难度非常大,很不明智。 “语言不可能太智能”,这句话没错,所以,在包,类命名上尽量遵循 CBC 原则,以减少无聊的机械劳动。 其实这是为了偶的原始需求, 懒... |
|
返回顶楼 | |
发表时间:2010-04-17
扩展的思路不错!
|
|
返回顶楼 | |