hession注解实现
原创 xingfu2017 发表于:2018-11-28 15:28:26
  阅读 :213   收藏   编辑

定义注解

/**
 * 自定义hessian注解
 *
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface HessianService {
 
    String description() default "";
    
    /**
     * 是否支持方法重载
     * @return
     */
    boolean overloadEnabled() default false; 
     
    /**
     * hessian远程访问后缀 ,打头需要加 “/”
     * @return
     */
    String suffix(); 
 
    /**
     * hessian远程访问前缀,一般情况固定为:http://ip:port/projectName/remote
     * @return
     */
    String prefix();   
}

定义server端扫描类HessianServerScannerConfigurer.java

import static org.springframework.util.Assert.notNull;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.remoting.caucho.HessianServiceExporter;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.support.XmlWebApplicationContext;

/**
 * hessian 接口服务端自动扫描注入
 * 
 * 原作者:http://git.oschina.net/huapox/hession_toolkit
 * 
 */
public class HessianServerScannerConfigurer implements
		BeanDefinitionRegistryPostProcessor, InitializingBean,
		ApplicationContextAware, BeanNameAware {

	private String beanName;
	private String basePackage;
	private boolean includeAnnotationConfig = true;
	private ApplicationContext applicationContext;

	// 实现了该接口
	private Class<?> markerInterface;
	// 配置了该注解
	private Class<? extends Annotation> annotationClass;
	// 存放spring 容器中的有接口的实现类的bean name
	private	Map<String, String> implClassContextName = new HashMap<String, String>();
	private BeanNameGenerator nameGenerator = new AnnotationBeanNameGenerator() {
		@Override
		protected String buildDefaultBeanName(BeanDefinition definition) {
			AnnotationMetadata metadata = ((ScannedGenericBeanDefinition)definition).getMetadata();
			Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(annotationClass.getName());
			String suffix = (String)annotationAttributes.get("suffix");
			return suffix;
		}
	};

	public void setBasePackage(String basePackage) {
		this.basePackage = basePackage;
	}

	public void setIncludeAnnotationConfig(boolean includeAnnotationConfig) {
		this.includeAnnotationConfig = includeAnnotationConfig;
	}

	public Class<?> getMarkerInterface() {
		return markerInterface;
	}

	public void setMarkerInterface(Class<?> markerInterface) {
		this.markerInterface = markerInterface;
	}

	public Class<? extends Annotation> getAnnotationClass() {
		return annotationClass;
	}

	public void setAnnotationClass(Class<? extends Annotation> annotationClass) {
		this.annotationClass = annotationClass;
	}

	public BeanNameGenerator getNameGenerator() {
		return nameGenerator;
	}

	public void setNameGenerator(BeanNameGenerator nameGenerator) {
		this.nameGenerator = nameGenerator;
	}

	@Override
	public void setBeanName(String name) {
		this.beanName = name;
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}

	@SuppressWarnings("unchecked")
	@Override
	public void afterPropertiesSet() throws Exception {
		notNull(this.basePackage, "Property 'basePackage' is required " + beanName);
		notNull(this.annotationClass, "Property 'annotationClass' is required " + beanName);
		
		XmlWebApplicationContext xmlContext = (XmlWebApplicationContext)applicationContext;
		do {
			DefaultListableBeanFactory beanFoctory = (DefaultListableBeanFactory)xmlContext.getAutowireCapableBeanFactory();
			Field findField = ReflectionUtils.findField(beanFoctory.getClass(), "singletonObjects");
			ReflectionUtils.makeAccessible(findField);
			Map<String, Object> field = (Map<String, Object>)ReflectionUtils.getField(findField, beanFoctory);
			for (Entry<String, Object> entry : field.entrySet()) {
				Class<?>[] interfaces = AopUtils.getTargetClass(entry.getValue()).getInterfaces();
				for (Class<?> interfaceClass : interfaces) {
					Annotation annotation = interfaceClass.getAnnotation(annotationClass);
					if (annotation != null) {
						implClassContextName.put(interfaceClass.getName(), entry.getKey());
					}
				}
			}
		} while ((xmlContext = (XmlWebApplicationContext)xmlContext.getParentBeanFactory()) != null);		
	}
	
	@Override
	public void postProcessBeanFactory(
			ConfigurableListableBeanFactory beanFactory) throws BeansException {
	}

	@Override
	public void postProcessBeanDefinitionRegistry(
			BeanDefinitionRegistry registry) throws BeansException {
		HessianClassPathScanner scan = new HessianClassPathScanner(registry);
		scan.setResourceLoader(this.applicationContext);
		scan.setBeanNameGenerator(this.nameGenerator);
		// 引入注解配置
		scan.setIncludeAnnotationConfig(this.includeAnnotationConfig);
		scan.registerFilters();

		String[] basePackages = StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
		scan.scan(basePackages);
	}


	private class HessianClassPathScanner extends ClassPathBeanDefinitionScanner {

		public HessianClassPathScanner(BeanDefinitionRegistry registry) {
			super(registry, false);
		}

		@Override
		public Set<BeanDefinitionHolder> doScan(String... basePackages) {
			Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
			if (beanDefinitions.isEmpty()) {
				logger.warn("No hessian was found in '"
						+ Arrays.toString(basePackages)
						+ "' package. Please check your configuration.");
			} else {
				for (BeanDefinitionHolder holder : beanDefinitions) {
					GenericBeanDefinition definition = (GenericBeanDefinition) holder.getBeanDefinition();

					if (logger.isDebugEnabled()) {
						logger.debug("Creating HessianServiceExporter with name '"
								+ holder.getBeanName() + "' and '"
								+ definition.getBeanClassName()
								+ "' serviceInterface");
					}

					// the mapper interface is the original class of the bean
					// but, the actual class of the bean is HessianServiceExporter
					definition.getPropertyValues().add("serviceInterface", definition.getBeanClassName());
					String beanNameRef = implClassContextName.get(definition.getBeanClassName());
					definition.getPropertyValues().add("service", new RuntimeBeanReference(beanNameRef));
					definition.setBeanClass(HessianServiceExporter.class);
				}
			} 
			return beanDefinitions;

		}

		@Override
		protected boolean isCandidateComponent(
				AnnotatedBeanDefinition beanDefinition) {
			return (beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent());
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		protected boolean checkCandidate(String beanName,
				BeanDefinition beanDefinition) throws IllegalStateException {
			String implBeanName = implClassContextName.get(beanDefinition.getBeanClassName());
			if (!(null==implBeanName||"".equals(implBeanName)) && super.checkCandidate(beanName, beanDefinition)) {
			//if (!StringUtils.isEmpty(implBeanName) && super.checkCandidate(beanName, beanDefinition)) {
				return true;
			} else {
				System.err.println("Skipping HessianServiceExporter with name '" + beanName
						+ "' and '" + beanDefinition.getBeanClassName()
						+ "' serviceInterface "
						+ ". Bean already defined with the same name!");
				logger.warn("Skipping HessianServiceExporter with name '" + beanName
						+ "' and '" + beanDefinition.getBeanClassName()
						+ "' serviceInterface "
						+ ". Bean already defined with the same name!");
				return false;
			}
		}

		public void registerFilters() {
			boolean acceptAllInterfaces = true;

		    // if specified, use the given annotation and / or marker interface
		    if (HessianServerScannerConfigurer.this.annotationClass != null) {
		      addIncludeFilter(new AnnotationTypeFilter(HessianServerScannerConfigurer.this.annotationClass));
		      acceptAllInterfaces = false;
		    }

		    // override AssignableTypeFilter to ignore matches on the actual marker interface
		    if (HessianServerScannerConfigurer.this.markerInterface != null) {
		      addIncludeFilter(new AssignableTypeFilter(HessianServerScannerConfigurer.this.markerInterface) {
		        @Override
		        protected boolean matchClassName(String className) {
		          return false;
		        }
		      });
		      acceptAllInterfaces = false;
		    }
			
			if (acceptAllInterfaces) {
				// default include filter that accepts all classes
				addIncludeFilter(new TypeFilter() {
					public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
						return true;
					}
				});
			}

			// exclude package-info.java
			addExcludeFilter(new TypeFilter() {
				public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
					String className = metadataReader.getClassMetadata().getClassName();
					return className.endsWith("package-info");
				}
			});
		}
	}
}

server端创建spring_hession_context.xml 

<bean class="com.xx.HessianServerScannerConfigurer">
	<!-- 基类包路径 -->
		<property name="basePackage" value="com.faceghost.elasticbg.base.service"></property>
		<!--hession自定义注解 -->
		<property name="annotationClass" value="com.xx.annotation.HessianService"></property>
</bean>

Server端web.xml初始化Hession

<servlet>
	<servlet-name>Hessian-servlet</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<load-on-startup>1</load-on-startup>
	<init-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:spring_hession_context.xml </param-value>
	</init-param>
</servlet>
<servlet-mapping>
	<servlet-name>Hessian-servlet</servlet-name>
	<url-pattern>/remote/*</url-pattern>
</servlet-mapping>

定义client端扫描类HessianClientScannerConfigurer.java

import static org.springframework.util.Assert.notNull;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;

import org.apache.commons.collections.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.remoting.caucho.HessianProxyFactoryBean;
import org.springframework.util.StringUtils;
 
/**
 * hessian 接口客户端自动扫描注入
 * 
 * 原作者:http://git.oschina.net/huapox/hession_toolkit
 * 
 */
public class HessianClientScannerConfigurer implements
        BeanDefinitionRegistryPostProcessor, InitializingBean,
        ApplicationContextAware, BeanNameAware {
 
    protected final Logger logger = LoggerFactory.getLogger(getClass());
 
    private String beanName;
    private String basePackage;
     
    private boolean includeAnnotationConfig = true;
 
    private ApplicationContext applicationContext;
 
    // 实现了该接口
    private Class<?> markerInterface;
    // 配置了该注解
    private Class<? extends Annotation> annotationClass;
 
    private BeanNameGenerator nameGenerator;
     
    @Override
    public void postProcessBeanFactory(
            ConfigurableListableBeanFactory beanFactory) throws BeansException {
    }
 
    @Override
    public void setBeanName(String name) {
        this.beanName = name;
    }
 
    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
        this.applicationContext = applicationContext;
    }
 
    @Override
    public void afterPropertiesSet() throws Exception {
        notNull(this.basePackage, "Property 'basePackage' is required " + beanName);
        Properties props = new Properties();
        for (Entry<Object, Object> resource : props.entrySet()) {
            System.setProperty((String)resource.getKey(), (String)resource.getValue());
        }
    }
     
    @Override
    public void postProcessBeanDefinitionRegistry(
            BeanDefinitionRegistry registry) throws BeansException {
        HessianClassPathScanner scan = new HessianClassPathScanner(registry);
        scan.setResourceLoader(this.applicationContext);
        scan.setBeanNameGenerator(this.nameGenerator);
        // 引入注解配置
        scan.setIncludeAnnotationConfig(this.includeAnnotationConfig);
        scan.registerFilters();
 
        String[] basePackages = StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
        scan.scan(basePackages);
    }
 
    public void setBasePackage(String basePackage) {
        this.basePackage = basePackage;
    }
 
    public void setIncludeAnnotationConfig(boolean includeAnnotationConfig) {
        this.includeAnnotationConfig = includeAnnotationConfig;
    }
 
    public Class<?> getMarkerInterface() {
        return markerInterface;
    }
 
    public void setMarkerInterface(Class<?> markerInterface) {
        this.markerInterface = markerInterface;
    }
 
    public Class<? extends Annotation> getAnnotationClass() {
        return annotationClass;
    }
 
    public void setAnnotationClass(Class<? extends Annotation> annotationClass) {
        this.annotationClass = annotationClass;
    }
 
    public BeanNameGenerator getNameGenerator() {
        return nameGenerator;
    }
 
    public void setNameGenerator(BeanNameGenerator nameGenerator) {
        this.nameGenerator = nameGenerator;
    }
     
     
    private class HessianClassPathScanner extends ClassPathBeanDefinitionScanner {
 
        public HessianClassPathScanner(BeanDefinitionRegistry registry) {
            super(registry, false);
        }
 
        @Override
        public Set<BeanDefinitionHolder> doScan(String... basePackages) {
            Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
            if (beanDefinitions.isEmpty()) {
                logger.warn("No hessian was found in '"
                        + Arrays.toString(basePackages)
                        + "' package. Please check your configuration.");
            } else {
                for (BeanDefinitionHolder holder : beanDefinitions) {
                    GenericBeanDefinition definition = (GenericBeanDefinition) holder.getBeanDefinition();
 
                    if (logger.isDebugEnabled()) {
                        logger.debug("Creating HessianFactoryBean with name '"
                                + holder.getBeanName() + "' and '"
                                + definition.getBeanClassName()
                                + "' hessianInterface");
                    }
                     
                    AnnotationMetadata metadata = ((ScannedGenericBeanDefinition)definition).getMetadata();
                    Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(annotationClass.getName());
                    String context = (String)annotationAttributes.get("prefix");
                    String suffix = (String)annotationAttributes.get("suffix");
                    Boolean overloadEnabled = MapUtils.getBoolean(annotationAttributes, "overloadEnabled", false);
                     
                     
                    definition.getPropertyValues().add("serviceUrl", context + suffix);
                    definition.getPropertyValues().add("serviceInterface", definition.getBeanClassName());
//                  新增overloadEnabled属性,并把它的值设置为true,默认是false,则Hessian就能支持方法的重载了
                    definition.getPropertyValues().add("overloadEnabled", overloadEnabled);
                    definition.setBeanClass(HessianProxyFactoryBean.class);
                     
                     
                    // the mapper interface is the original class of the bean
                    // but, the actual class of the bean is HessianFactoryBean
//                  definition.getPropertyValues().add("hessianInterface", definition.getBeanClassName());
//                  definition.setBeanClass(HessianFactoryBean.class);
                }
            }
            return beanDefinitions;
 
        }
 
        @Override
        protected boolean isCandidateComponent(
                AnnotatedBeanDefinition beanDefinition) {
            return (beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent());
        }
 
        /**
         * {@inheritDoc}
         */
        @Override
        protected boolean checkCandidate(String beanName,
                BeanDefinition beanDefinition) throws IllegalStateException {
            if (super.checkCandidate(beanName, beanDefinition)) {
                return true;
            } else {
                logger.warn("Skipping HessianFactoryBean with name '" + beanName
                        + "' and '" + beanDefinition.getBeanClassName()
                        + "' hessianInterface"
                        + ". Bean already defined with the same name!");
                return false;
            }
        }
 
        public void registerFilters() {
            boolean acceptAllInterfaces = true;
 
            // if specified, use the given annotation and / or marker interface
            if (HessianClientScannerConfigurer.this.annotationClass != null) {
              addIncludeFilter(new AnnotationTypeFilter(HessianClientScannerConfigurer.this.annotationClass));
              acceptAllInterfaces = false;
            }
 
            // override AssignableTypeFilter to ignore matches on the actual marker interface
            if (HessianClientScannerConfigurer.this.markerInterface != null) {
              addIncludeFilter(new AssignableTypeFilter(HessianClientScannerConfigurer.this.markerInterface) {
                @Override
                protected boolean matchClassName(String className) {
                  return false;
                }
              });
              acceptAllInterfaces = false;
            }
             
            if (acceptAllInterfaces) {
                // default include filter that accepts all classes
                addIncludeFilter(new TypeFilter() {
                    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
                        return true;
                    }
                });
            }
 
            // exclude package-info.java
            addExcludeFilter(new TypeFilter() {
                public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
                    String className = metadataReader.getClassMetadata().getClassName();
                    return className.endsWith("package-info");
                }
            });
        }
    }
}

client端创建spring_hession_context.xml 

<bean class="com.xx.HessianClientScannerConfigurer">
		<!-- 基类包路径 -->
		<property name="basePackage" value="com.xx.service" />
		<!--hession自定义注解 -->
		<property name="annotationClass" value="com.xx.annotation.HessianService" />
</bean>

使用

@HessianService(prefix="http://localhost:port/projectName/remote",suffix="/testService")
public interface TestService {
    //...
}