Spring自定义配置Schema可扩展(二)

 更新时间:2016年01月28日 11:30:50   作者:王成委  
这篇文章主要介绍了Spring自定义配置Schema可扩展(二)的相关资料,需要的朋友可以参考下
(福利推荐:【腾讯云】服务器最新限时优惠活动,云服务器1核2G仅99元/年、2核4G仅768元/3年,立即抢购>>>:9i0i.cn/qcloud

(福利推荐:你还在原价购买阿里云服务器?现在阿里云0.8折限时抢购活动来啦!4核8G企业云服务器仅2998元/3年,立即抢购>>>:9i0i.cn/aliyun

命名空间支持

要实现命名空间支持,需要继承自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
*/
@WebService
public 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

通过以上内容的介绍本次扩展基本上就实现了。

相关文章

  • java 反射getClass .class 的使用方法示例

    java 反射getClass .class 的使用方法示例

    这篇文章主要介绍了java 反射getClass .class 的使用方法,结合实例形式分析了java类反射机制的相关操作技巧,需要的朋友可以参考下
    2019-11-11
  • Java十大经典排序算法图解

    Java十大经典排序算法图解

    这篇文章主要介绍了Java十大经典排序算法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-11-11
  • 解决mybatis-plus自定义xml的坑

    解决mybatis-plus自定义xml的坑

    这篇文章主要介绍了解决mybatis-plus自定义xml的坑,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • Spring AOP基本概念

    Spring AOP基本概念

    这篇文章主要为大家详细介绍了spring基础概念AOP与动态代理,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能给你带来帮助
    2021-07-07
  • Spring data elasticsearch使用方法详解

    Spring data elasticsearch使用方法详解

    这篇文章主要介绍了Spring data elasticsearch使用方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • javascript最新2020经典面试题

    javascript最新2020经典面试题

    这篇文章主要介绍了javascript最新2020经典面试题的相关内容,有需要的朋友们可以学习下。
    2020-02-02
  • java 注解annotation的使用以及反射如何获取注解

    java 注解annotation的使用以及反射如何获取注解

    这篇文章主要介绍了java 注解annotation的使用以及反射如何获取注解的相关资料,需要的朋友可以参考下
    2017-01-01
  • MyBatis-Plus自动填充功能失效导致的原因及解决

    MyBatis-Plus自动填充功能失效导致的原因及解决

    这篇文章主要介绍了MyBatis-Plus自动填充功能失效导致的原因及解决,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02
  • Java数据结构及算法实例:插入排序 Insertion Sort

    Java数据结构及算法实例:插入排序 Insertion Sort

    这篇文章主要介绍了Java数据结构及算法实例:插入排序 Insertion Sort,本文直接给出实例代码,代码中包含详细注释,需要的朋友可以参考下
    2015-06-06
  • MyBatis查询时属性名和字段名不一致问题的解决方法

    MyBatis查询时属性名和字段名不一致问题的解决方法

    这篇文章主要给大家介绍了关于MyBatis查询时属性名和字段名不一致问题的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01

最新评论


http://www.vxiaotou.com