命名空間支持
要實(shí)現(xiàn)命名空間支持,需要繼承自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 {@Overridepublic void init() {// TODO Auto-generated method stubthis.registerBeanDefinitionParser("annotation-endpoint", new AnnotationBeanDefinitionParser(EndpointBeanProcessor.class));}}通過registerBeanDefinitionParser方法講配置支持添加到Spring中。annotation-endpoint是配置支持的元素。AnnotationBeanDefinitionParser是處理配置的類。EndpointBeanProcessor是處理@Endpoint注解的Bean的類,后面會(huì)有詳細(xì)的講述。
處理配置
需要實(shí)現(xiàn)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;}@Overridepublic 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的應(yīng)用參見Spring官方文檔。
Bean注冊(cè)工具類
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;@Overridepublic 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);}@Overridepublic void setApplicationContext(ApplicationContext applicationContext)throws BeansException {this.applicationContext = applicationContext;this.beanRegistry = new BeanRegistry(this.applicationContext);}@Overridepublic 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;}@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName)throws BeansException {return bean;}@Overridepublic 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}注解*/@Overridepublic 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);}}}這里已經(jīng)實(shí)現(xiàn)了注解的掃描。然后需要在postProcessAfterInitialization方法中寫業(yè)務(wù)處理代碼。AfterInitialization表示Bean已經(jīng)創(chuàng)建并且注入屬性。
postProcessBeforeInitialization主要是為了在Bean實(shí)例化時(shí)注入屬性。
讓Spring識(shí)別擴(kuò)展
首先在classpath的META-INF下創(chuàng)建spring.handlers,內(nèi)容如下
http/://www.codestd.com/schema/std/ws=com.codestd.spring.cxf.config.schema.WebServiceAnnotationNamespaceHandler
在這個(gè)文件中指明了哪個(gè)命名空間需要哪個(gè)類來處理。
然后再創(chuàng)建spring.schemas
http/://www.codestd.com/schema/std/ws/stdws-1.0.xsd=META-INF/schema/stdws-1.0.xsd
指明了Sechma文件的位置,Spring會(huì)使用這里制定的xsd文件來驗(yàn)證配置是否正確。
測(cè)試
創(chuàng)建接口
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);}實(shí)現(xiàn)類
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{@Overridepublic String syHi(String name) {return "Hello "+name;}}測(cè)試用例
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations={"classpath:applicationContext.xml"})public class InitializationTest {@Testpublic void test(){}}在處理類中有一段代碼是將有@Endpoint注解的類都打印出來,所以如果類名被打印出來就表示配置正常了。
運(yùn)行測(cè)試用例
控制臺(tái)能夠看到
class com.codestd.spring.cxf.ws.HelloServiceImpl
通過以上內(nèi)容的介紹本次擴(kuò)展基本上就實(shí)現(xiàn)了。
新聞熱點(diǎn)
疑難解答
圖片精選