don't repeat yourself -约定优于配置(spring领域约定)
小弟刚学习spring,发现一个事情就是配置xml相当麻烦,而且有很多地方都是重复性的工作,于是本着DRY,约定优于配置,越简单越好和闲来没事干的精神对spring做了一点小的的学习,由于spring刚学,很多做得不对的,还望指出。
约定,现在我们假设约定如下:

只要在dao包下面,且其超类实现了Dao接口的类 我们就认为他是dao类
只要在service包下面,且其超类实现了service接口的类,我们就认为他是service类
只要在operation包下面,且其超类实现了operation接口的类,我们就认为他是operation类。
所有的entity类都放在entity包下面。
有了上面的约定在根据服务调用关系operation-service-dao,我们就进行动态的注入,而不是每次都要写同样的配置代码了。
实现思想:自定义一个BeanDefinitionParser类似于component-scan,并根据以上规则扫描和注入组件。
代码:
重写org.springframework.context.config.ContextNamespaceHandler增加一个解析器。
public class ContextNamespaceHandler extends NamespaceHandlerSupport{public void init(){ ......... registerBeanDefinitionParser("wangscu-component-scan", new SimpleComponentScanBeanDefinitionParser());}} @Overridepublic BeanDefinition parse(Element element, ParserContext parserContext){String[] packages = StringUtils.tokenizeToStringArray(element.getAttribute(基包名称),ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);SimpleBeanDefinitionScanner scanner = configureScanner(element, parserContext);Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(packages);registerComponents(parserContext.getReaderContext(), beanDefinitions, element);return null;}private void doServiceInjection(ScannedGenericBeanDefinition scannedGenericBeanDefinition, String basePackage){AnnotationMetadata meta = scannedGenericBeanDefinition.getMetadata();String className = meta.getClassName();try{Class<? extends Service> service = (Class<? extends Service>) getClass().getClassLoader().loadClass(className);Field[] fields = service.getDeclaredFields();for (Field field : fields){Class<? extends Object> dao = field.getType();if (dao.getName().startsWith(basePackage + ".server.dao.")){String name = SimpleBeanNameGenerator.getDaoName(dao);Object val = parsePropertyValue(scannedGenericBeanDefinition, field.getName(), name);PropertyValue pv = new PropertyValue(field.getName(), val);scannedGenericBeanDefinition.getPropertyValues().addPropertyValue(pv);break;}}}catch (Exception e){}}@Overrideprotected Boolean matchSuperClass(String superClassName){if (superClassName.startsWith("java.")) { return null; }try{Class<? extends Object> clazz = getClass().getClassLoader().loadClass(superClassName);Class<?>[] array = clazz.getInterfaces();for (Class<?> clazz1 : array){if (clazz1 == SimpleComponentScanBeanDefinitionParser.DAO){return Boolean.TRUE;}else if (clazz1 == SimpleComponentScanBeanDefinitionParser.SERVICE){return Boolean.TRUE;}else if (clazz1 == SimpleComponentScanBeanDefinitionParser.OPERATION) { return Boolean.TRUE; }}}catch (Exception e){}return null;}public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry){if (definition instanceof GenericBeanDefinition){try{String beanName = definition.getBeanClassName();Class<? extends Object> beanClass;beanClass = getClass().getClassLoader().loadClass(beanName);Class<?>[] array = beanClass.getSuperclass().getInterfaces();for (Class<?> clazz1 : array){if (clazz1 == SimpleComponentScanBeanDefinitionParser.DAO){return getDaoName(beanClass.getInterfaces()[0]);}else if (clazz1 == SimpleComponentScanBeanDefinitionParser.SERVICE){return getServiceName(beanClass.getInterfaces()[0]);}else if (clazz1 == SimpleComponentScanBeanDefinitionParser.OPERATION) { return getOperationName(beanClass.getInterfaces()[0]); }}}catch (Exception e){}}return super.generateBeanName(definition, registry);}public static String getDaoName(Class<? extends Object> clazz){String beanName = clazz.getSimpleName();return beanName.substring(0, 1).toLowerCase() + beanName.substring(1);}public static String getOperationName(Class<? extends Object> clazz){String beanName = clazz.getSimpleName();return beanName.substring(0, 1).toLowerCase() + beanName.substring(1);}public static String getServiceName(Class<? extends Object> clazz){String beanName = clazz.getSimpleName();return beanName.substring(0, 1).toLowerCase() + beanName.substring(1);}<?xml version="1.0" encoding="UTF-8"?> ....<context:wangscu-component-scan base-package="com.wangscu.core" />....</beans>
package com.wangscu.spring;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.wangscu.core.server.operation.用户.通过标识符获得用户;public class EntryPoint{public static void main(String[] args) throws Exception{String[] moudles = new String[]{ "moudle.xml" };ApplicationContext context = new ClassPathXmlApplicationContext(moudles);通过标识符获得用户 operation = context.getBean("通过标识符获得用户", 通过标识符获得用户.class);operation.setId(1l);operation.execute();System.out.println(operation.getUser().getName());}}
这种不能用了么?这种不能用了么?