当前位置: 移动技术网 > IT编程>开发语言>Java > Spring自定义配置Schema可扩展(二)

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

2019年07月22日  | 移动技术网IT编程  | 我要评论

厦门小鱼社区,普法栏目剧兄妹劫,非农是什么意思

命名空间支持

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

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网