基于Spring可扩展Schema自定义配置(2)
来源:互联网 发布:王保保 知乎 编辑:程序博客网 时间:2024/06/08 13:58
本章主要实现配置支持,注解扫描等功能。为本次教程的核心
命名空间支持
要实现命名空间支持,需要继承自NamespaceHandlerSupport
。
package com.codestd.spring.cxf.config.schema;import org.springframework.beans.factory.xml.NamespaceHandlerSupport;import com.codestd.spring.cxf.config.EndpointBeanProcessor;/** * 处理命名空间 * @author jaune(Wang Chengwei) * @since 1.0.0 */public class WebServiceAnnotationNamespaceHandler extends NamespaceHandlerSupport { @Override public void init() { // TODO Auto-generated method stub this.registerBeanDefinitionParser("annotation-endpoint", new AnnotationBeanDefinitionParser(EndpointBeanProcessor.class)); }}
通过registerBeanDefinitionParser方法讲配置支持添加到Spring中。annotation-endpoint
是配置支持的元素。AnnotationBeanDefinitionParser
是处理配置的类。EndpointBeanProcessor
是处理@Endpoint
注解的Bean的类,后面会有详细的讲述。
处理配置
需要实现BeanDefinitionParser
package com.codestd.spring.cxf.config.schema;import org.springframework.beans.factory.config.BeanDefinition;import org.springframework.beans.factory.support.RootBeanDefinition;import org.springframework.beans.factory.xml.BeanDefinitionParser;import org.springframework.beans.factory.xml.ParserContext;import org.springframework.util.StringUtils;import org.w3c.dom.Element;/** * @author jaune(Wang Chengwei) * @since 1.0.0 */public class AnnotationBeanDefinitionParser implements BeanDefinitionParser { private final Class<?> beanClass; public AnnotationBeanDefinitionParser(Class<?> beanClass) { this.beanClass = beanClass; } @Override public BeanDefinition parse(Element element, ParserContext parserContext) { RootBeanDefinition beanDefinition = new RootBeanDefinition(); beanDefinition.setBeanClass(beanClass); beanDefinition.setLazyInit(false); String id = element.getAttribute("id"); if(id == null || id.length() == 0 ){ String name = element.getAttribute("name"); if(!StringUtils.isEmpty(name)) id = name; else id = beanClass.getName(); } if (parserContext.getRegistry().containsBeanDefinition(id)) { throw new IllegalStateException("Duplicate spring bean id " + id); } parserContext.getRegistry().registerBeanDefinition(id, beanDefinition); String annotationPackage = element.getAttribute("package"); if(!StringUtils.isEmpty(annotationPackage)) beanDefinition.getPropertyValues().add("annotationPackage", annotationPackage); return beanDefinition; }}
BeanDefinitionParser的应用参见Spring官方文档。
Bean注册工具类
package com.codestd.spring.cxf.config;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.BeanDefinition;import org.springframework.beans.factory.support.BeanDefinitionBuilder;import org.springframework.beans.factory.support.BeanDefinitionRegistry;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.context.ConfigurableApplicationContext;/** * Registry Bean. Must inject the spring ApplicationContext. * @author jaune(Wang Chengwei) * @since 1.0.0 */public class BeanRegistry implements ApplicationContextAware{ private ApplicationContext applicationContext; private ConfigurableApplicationContext configurableApplicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; if(applicationContext instanceof ConfigurableApplicationContext){ this.configurableApplicationContext = (ConfigurableApplicationContext)this.applicationContext; } } public BeanRegistry(){ } public BeanRegistry(ApplicationContext applicationContext){ this.setApplicationContext(applicationContext); } public BeanDefinition register(Class<?> clazz){ if(configurableApplicationContext == null)return null; BeanDefinitionRegistry beanDefinitonRegistry = (BeanDefinitionRegistry)configurableApplicationContext.getBeanFactory(); BeanDefinitionBuilder beanDefinitionBuilder = this.createBuilder(clazz); BeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition(); beanDefinitonRegistry.registerBeanDefinition(clazz.getName(),beanDefinition); return beanDefinition; } private BeanDefinitionBuilder createBuilder(Class<?> clazz){ BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz); return beanDefinitionBuilder; }}
处理@Endpoint
package com.codestd.spring.cxf.config;import org.springframework.beans.BeansException;import org.springframework.beans.factory.DisposableBean;import org.springframework.beans.factory.config.BeanFactoryPostProcessor;import org.springframework.beans.factory.config.BeanPostProcessor;import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;import org.springframework.beans.factory.support.BeanDefinitionRegistry;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;import org.springframework.core.type.filter.AnnotationTypeFilter;import org.springframework.util.StringUtils;import com.codestd.spring.cxf.annotation.Endpoint;/** * @author jaune(WangChengwei) * @since 1.0.0 */public class EndpointBeanProcessor implements BeanFactoryPostProcessor, DisposableBean, BeanPostProcessor, ApplicationContextAware{ private final String COMMA_SPLIT_PATTERN = ","; private ApplicationContext applicationContext; private String annotationPackage; private String[] annotationPackages; private BeanRegistry beanRegistry; public void setAnnotationPackage(String annotationPackage) { this.annotationPackage = annotationPackage; if(!StringUtils.isEmpty(this.annotationPackage)) this.annotationPackages = this.annotationPackage.split(this.COMMA_SPLIT_PATTERN); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; this.beanRegistry = new BeanRegistry(this.applicationContext); } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if(!this.isMatchPackage(bean))return bean; Endpoint endpoint = bean.getClass().getAnnotation(Endpoint.class); if(endpoint != null){ System.out.println(bean.getClass()); } return bean; } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } @Override public void destroy() throws Exception { } /** * 包是否匹配 * @param bean * @return */ private boolean isMatchPackage(Object bean){ if (annotationPackages == null || annotationPackages.length == 0) { return true; } String beanClassName = bean.getClass().getName(); for (String pkg : annotationPackages) { if (beanClassName.startsWith(pkg)) { return true; } } return false; } /** * 扫描{@link com.codestd.spring.cxf.annotation.Endpoint}注解 */ @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { if (annotationPackage == null || annotationPackage.length() == 0) { return; } if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry beanDefinitionRegistry = (BeanDefinitionRegistry)beanFactory; ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(beanDefinitionRegistry,true); AnnotationTypeFilter filter = new AnnotationTypeFilter(Endpoint.class); scanner.addIncludeFilter(filter); scanner.scan(annotationPackages); } }}
这里已经实现了注解的扫描。然后需要在postProcessAfterInitialization
方法中写业务处理代码。AfterInitialization表示Bean已经创建并且注入属性。 postProcessBeforeInitialization
主要是为了在Bean实例化时注入属性。
让Spring识别扩展
首先在classpath的META-INF下创建spring.handlers,内容如下
http\://www.codestd.com/schema/std/ws=com.codestd.spring.cxf.config.schema.WebServiceAnnotationNamespaceHandler
在这个文件中指明了哪个命名空间需要哪个类来处理。
然后再创建spring.schemas
http\://www.codestd.com/schema/std/ws/stdws-1.0.xsd=META-INF/schema/stdws-1.0.xsd
指明了Sechma文件的位置,Spring会使用这里制定的xsd文件来验证配置是否正确。
测试
创建接口
package com.codestd.spring.cxf.ws;import javax.jws.WebService;/** * @author jaune(Wang Chengwei) * @since 1.0.0 */@WebServicepublic interface HelloService { public String syHi(String name);}
实现类
package com.codestd.spring.cxf.ws;import javax.jws.WebService;import com.codestd.spring.cxf.annotation.Endpoint;/** * @author jaune(Wang Chengwei) * @since 1.0.0 */@Endpoint(address="HelloService", id = "HelloServiceEndpoint")@WebService(endpointInterface="com.codestd.spring.cxf.ws.HelloService")public class HelloServiceImpl implements HelloService{ @Override public String syHi(String name) { return "Hello "+name; }}
测试用例
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations={"classpath:applicationContext.xml"})public class InitializationTest { @Test public void test(){ }}
在处理类中有一段代码是将有@Endpoint注解的类都打印出来,所以如果类名被打印出来就表示配置正常了。
运行测试用例
控制台能够看到
class com.codestd.spring.cxf.ws.HelloServiceImpl
本次扩展基本实现。
本此教程的内容可以在Spring官方文档第42章中找到。
Note
本次并没有实现自动发布WebService的功能,这块儿功能比较复杂暂时还没有实现,如果实现会在后面的博文中补充。
- 基于Spring可扩展Schema自定义配置(2)
- 基于Spring可扩展Schema自定义配置(1)
- spring-基于Spring可扩展Schema提供自定义配置
- 基于Spring可扩展Schema提供自定义配置支持
- 基于Spring可扩展Schema提供自定义配置支持
- 基于Spring可扩展Schema提供自定义配置支持
- 基于Spring可扩展Schema提供自定义配置支持
- 基于Spring可扩展Schema提供自定义配置支持
- 基于Spring可扩展Schema提供自定义配置支持
- 基于Spring可扩展Schema提供自定义配置支持
- 基于Spring可扩展Schema提供自定义配置支持
- 基于Spring可扩展Schema提供自定义配置支持
- 基于Spring可扩展Schema提供自定义配置支持
- 基于Spring可扩展Schema提供自定义配置支持
- 基于Spring可扩展Schema提供自定义配置支持
- 基于Spring可扩展Schema提供自定义配置支持
- 基于Spring可扩展Schema提供自定义配置支持
- 基于Spring可扩展Schema提供自定义配置支持
- Android Notification通知栏开发详解
- android gridview 内容不居中问题
- 正则表达式实例
- Linux下查看CPU核心数命令
- js array to json
- 基于Spring可扩展Schema自定义配置(2)
- 使用Android Studio发布私有库到仓库中心
- Visual Studio 2015 出现 NuGet 安装程序包错误解决方法
- President Obama's Final State Of The Union Address
- SELECT INTO 和 INSERT INTO SELECT 两种表复制语句
- UIUC大学之Coursera课程Text Retrieval and Search Engines:Week 1 Practice Quiz
- html header内容
- linux 存储映射
- python2.7 sklearn 使用报错ImportError: DLL load failed: 找不到指定模块