Spring 注解发布RMI/HTTPInvoker/Hessian/Burlap服务

使用自定义的spring注解标签发布RMI/HTTPInvoker/Hessian/Burlap远程服务。

1.依赖jar的pom.xml配置

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>cn.slimsmart.spring.rpc.annotation.demo</groupId>
	<artifactId>spring-rpc-annotation-demo</artifactId>
	<version>1.0.0</version>
	<packaging>jar</packaging>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.7</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>4.0.9.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-expression</artifactId>
			<version>4.0.9.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>4.0.9.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>4.0.9.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>4.0.9.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>com.caucho</groupId>
			<artifactId>hessian</artifactId>
			<version>4.0.38</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>4.0.9.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.eclipse.jetty</groupId>
			<artifactId>jetty-webapp</artifactId>
			<version>8.1.3.v20120416</version>
		</dependency>
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>1.8.5</version>
		</dependency>
	</dependencies>
	
	<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.0.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-eclipse-plugin</artifactId>
                <version>2.9</version>
                <configuration>
                    <downloadSources>true</downloadSources>
                    <downloadJavadocs>true</downloadJavadocs>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
2.改造spring,使其支持注解发布不同服务

1)定义远程发布服务注解

RemoteService.java

package org.springframework.remoting.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.stereotype.Component;

/**
 * 远程发布注解RemoteService
 */
@Target({ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface RemoteService {

    ServiceType serviceType() default ServiceType.HTTP;

    Class<?> serviceInterface();
}
2)RmiServiceProperty.java

RemoteService辅助标签,在发布RMI服务时,用来指定RMI服务发布的端口。

package org.springframework.remoting.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.rmi.registry.Registry;

import org.springframework.stereotype.Component;

/**
 * RemoteService辅助标签,在发布RMI服务时,用来指定RMI服务发布的端口。
 */
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface RmiServiceProperty {
    int registryPort() default Registry.REGISTRY_PORT;
}
3)定义发布服务的类型枚举
package org.springframework.remoting.annotation;

/**
 * ServiceType,指定发布服务的类型
 */
public enum ServiceType {
    HTTP, BURLAP, HESSIAN, RMI
}
4)注解解析实现
ServiceAnnotationBeanPostProcessor .java

package org.springframework.factory.annotation;

import java.rmi.RemoteException;

import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.remoting.annotation.RemoteService;
import org.springframework.remoting.annotation.RmiServiceProperty;
import org.springframework.remoting.annotation.ServiceType;
import org.springframework.remoting.caucho.BurlapServiceExporter;
import org.springframework.remoting.caucho.HessianServiceExporter;
import org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter;
import org.springframework.remoting.rmi.RmiServiceExporter;

/**
 * 解析RemoteService注解标签,发布服务
 */
@SuppressWarnings("deprecation")
public class ServiceAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements PriorityOrdered {

	private int order = Ordered.LOWEST_PRECEDENCE - 1;

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		RemoteService service = AnnotationUtils.findAnnotation(bean.getClass(), RemoteService.class);
		Object resultBean = bean;
		if (null != service) {
			//HttpInvoker 服务发布
			if (ServiceType.HTTP == service.serviceType()) {
				if (!beanName.startsWith("/")) {
					throw new FatalBeanException("Exception initializing  HttpInvokerService for " + beanName + ",beanName should bean start with \"/\".");
				}

				HttpInvokerServiceExporter httpInvokerServiceExporter = new HttpInvokerServiceExporter();
				httpInvokerServiceExporter.setServiceInterface(service.serviceInterface());
				httpInvokerServiceExporter.setService(bean);
				httpInvokerServiceExporter.afterPropertiesSet();
				resultBean = httpInvokerServiceExporter;
			//Hessian 服务发布
			} else if (ServiceType.HESSIAN == service.serviceType()) {
				if (!beanName.startsWith("/")) {
					throw new FatalBeanException("Exception initializing  HessianService for " + beanName + ",beanName should bean start with \"/\".");
				}
				HessianServiceExporter hessianServiceExporter = new HessianServiceExporter();
				hessianServiceExporter.setServiceInterface(service.serviceInterface());
				hessianServiceExporter.setService(bean);
				hessianServiceExporter.afterPropertiesSet();
				resultBean = hessianServiceExporter;
			//Burlap 服务发布
			} else if (ServiceType.BURLAP == service.serviceType()) {
				if (!beanName.startsWith("/")) {
					throw new FatalBeanException("Exception initializing BurlapService for " + beanName + ",beanName should bean start with \"/\".");
				}
				BurlapServiceExporter burlapServiceExporter = new BurlapServiceExporter();
				burlapServiceExporter.setServiceInterface(service.serviceInterface());
				burlapServiceExporter.setService(bean);
				burlapServiceExporter.afterPropertiesSet();
				resultBean = burlapServiceExporter;
		    //RIM 服务发布
			} else if (ServiceType.RMI == service.serviceType()) {
				RmiServiceExporter rmiServiceExporter = new RmiServiceExporter();
				rmiServiceExporter.setServiceInterface(service.serviceInterface());
				rmiServiceExporter.setService(bean);
				RmiServiceProperty rmiServiceProperty = bean.getClass().getAnnotation(RmiServiceProperty.class);
				if (rmiServiceProperty != null) {
					rmiServiceExporter.setRegistryPort(rmiServiceProperty.registryPort());
				}
				String serviceName = beanName;
				if (serviceName.startsWith("/")) {
					serviceName = serviceName.substring(1);
				}
				rmiServiceExporter.setServiceName(serviceName);
				try {
					rmiServiceExporter.afterPropertiesSet();
				} catch (RemoteException remoteException) {
					throw new FatalBeanException("Exception initializing RmiServiceExporter", remoteException);
				}
				resultBean = rmiServiceExporter;
			}
		}
		return resultBean;
	}

	@Override
	public int getOrder() {
		return order;
	}
}
5.重写spring注解配置工具类AnnotationConfigUtils.java 需与spring的在同一包目录
/*
 * Copyright 2002-2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.context.annotation;

import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.factory.annotation.ServiceAnnotationBeanPostProcessor;
import org.springframework.util.ClassUtils;


/**
 * Utility class that allows for convenient registration of common
 * {@link org.springframework.beans.factory.config.BeanPostProcessor} and
 * {@link org.springframework.beans.factory.config.BeanFactoryPostProcessor}
 * definitions for annotation-based configuration. Also registers a common
 * {@link org.springframework.beans.factory.support.AutowireCandidateResolver}.
 *
 * @author Mark Fisher
 * @author Juergen Hoeller
 * @author Chris Beams
 * @author Phillip Webb
 * @since 2.5
 * @see ContextAnnotationAutowireCandidateResolver
 * @see CommonAnnotationBeanPostProcessor
 * @see ConfigurationClassPostProcessor
 * @see org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
 * @see org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor
 * @see org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor
 */
//重写Spring框架 AnnotationConfigUtils,与spring相同包目录
public class AnnotationConfigUtils {

	/**
	 * The bean name of the internally managed Configuration annotation processor.
	 */
	public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =
			"org.springframework.factory.annotation.internalConfigurationAnnotationProcessor";
	/***
	 * 定义注解解析实现
	 */
	public static final String SERVICE_ANNOTATION_PROCESSOR_BEAN_NAME = 
			"org.springframework.remoting.ServiceAnnotationBeanPostProcessor";

	/**
	 * The bean name of the internally managed BeanNameGenerator for use when processing
	 * {@link Configuration} classes. Set by {@link AnnotationConfigApplicationContext}
	 * and {@code AnnotationConfigWebApplicationContext} during bootstrap in order to make
	 * any custom name generation strategy available to the underlying
	 * {@link ConfigurationClassPostProcessor}.
	 * @since 3.1.1
	 */
	public static final String CONFIGURATION_BEAN_NAME_GENERATOR =
			"org.springframework.context.annotation.internalConfigurationBeanNameGenerator";

	/**
	 * The bean name of the internally managed Autowired annotation processor.
	 */
	public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME =
			"org.springframework.context.annotation.internalAutowiredAnnotationProcessor";

	/**
	 * The bean name of the internally managed Required annotation processor.
	 */
	public static final String REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME =
			"org.springframework.context.annotation.internalRequiredAnnotationProcessor";

	/**
	 * The bean name of the internally managed JSR-250 annotation processor.
	 */
	public static final String COMMON_ANNOTATION_PROCESSOR_BEAN_NAME =
			"org.springframework.context.annotation.internalCommonAnnotationProcessor";

	/**
	 * The bean name of the internally managed JPA annotation processor.
	 */
	public static final String PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME =
			"org.springframework.context.annotation.internalPersistenceAnnotationProcessor";


	private static final String PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME =
			"org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor";


	/**
	 * The bean name of the internally managed Scheduled annotation processor.
	 * <p>ATTENTION:</p> This constant is meant for internal use only. The value is stable
	 * but don't rely on the presence of this constant declaration; rather copy the value.
	 */
	public static final String SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME =
			"org.springframework.context.annotation.internalScheduledAnnotationProcessor";

	/**
	 * The bean name of the internally managed Async annotation processor.
	 * <p>ATTENTION:</p> This constant is meant for internal use only. The value is stable
	 * but don't rely on the presence of this constant declaration; rather copy the value.
	 */
	public static final String ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME =
			"org.springframework.context.annotation.internalAsyncAnnotationProcessor";

	/**
	 * The bean name of the internally managed AspectJ async execution aspect.
	 * <p>ATTENTION:</p> This constant is meant for internal use only. The value is stable
	 * but don't rely on the presence of this constant declaration; rather copy the value.
	 */
	public static final String ASYNC_EXECUTION_ASPECT_BEAN_NAME =
			"org.springframework.scheduling.config.internalAsyncExecutionAspect";

	/**
	 * The class name of the AspectJ async execution aspect.
	 * <p>ATTENTION:</p> This constant is meant for internal use only. The value is stable
	 * but don't rely on the presence of this constant declaration; rather copy the value.
	 */
	public static final String ASYNC_EXECUTION_ASPECT_CLASS_NAME =
			"org.springframework.scheduling.aspectj.AnnotationAsyncExecutionAspect";

	/**
	 * The name of the AspectJ async execution aspect @{@code Configuration} class.
	 * <p>ATTENTION:</p> This constant is meant for internal use only. The value is stable
	 * but don't rely on the presence of this constant declaration; rather copy the value.
	 */
	public static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME =
			"org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";

	/**
	 * The bean name of the internally managed cache advisor.
	 * <p>ATTENTION:</p> This constant is meant for internal use only. The value is stable
	 * but don't rely on the presence of this constant declaration; rather copy the value.
	 */
	public static final String CACHE_ADVISOR_BEAN_NAME =
			"org.springframework.cache.config.internalCacheAdvisor";

	/**
	 * The bean name of the internally managed cache aspect.
	 * <p>ATTENTION:</p> This constant is meant for internal use only. The value is stable
	 * but don't rely on the presence of this constant declaration; rather copy the value.
	 */
	public static final String CACHE_ASPECT_BEAN_NAME =
			"org.springframework.cache.config.internalCacheAspect";

	/**
	 * The class name of the AspectJ caching aspect.
	 * <p>ATTENTION:</p> This constant is meant for internal use only. The value is stable
	 * but don't rely on the presence of this constant declaration; rather copy the value.
	 */
	public static final String CACHE_ASPECT_CLASS_NAME =
			"org.springframework.cache.aspectj.AnnotationCacheAspect";

	/**
	 * The name of the AspectJ caching aspect @{@code Configuration} class.
	 * <p>ATTENTION:</p> This constant is meant for internal use only. The value is stable
	 * but don't rely on the presence of this constant declaration; rather copy the value.
	 */
	public static final String CACHE_ASPECT_CONFIGURATION_CLASS_NAME =
			"org.springframework.cache.aspectj.AspectJCachingConfiguration";


	private static final boolean jsr250Present =
			ClassUtils.isPresent("javax.annotation.Resource", AnnotationConfigUtils.class.getClassLoader());

	private static final boolean jpaPresent =
			ClassUtils.isPresent("javax.persistence.EntityManagerFactory", AnnotationConfigUtils.class.getClassLoader()) &&
			ClassUtils.isPresent(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, AnnotationConfigUtils.class.getClassLoader());


	/**
	 * Register all relevant annotation post processors in the given registry.
	 * @param registry the registry to operate on
	 */
	public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
		registerAnnotationConfigProcessors(registry, null);
	}

	/**
	 * Register all relevant annotation post processors in the given registry.
	 * @param registry the registry to operate on
	 * @param source the configuration source element (already extracted)
	 * that this registration was triggered from. May be {@code null}.
	 * @return a Set of BeanDefinitionHolders, containing all bean definitions
	 * that have actually been registered by this call
	 */
	public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
			BeanDefinitionRegistry registry, Object source) {

		DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
		if (beanFactory != null) {
			if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
				beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
			}
			if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
				beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
			}
		}

		Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);
		
		/**
		 * 非ServiceAnnotationBeanPostProcessor类处理
		 */
		if (!registry.containsBeanDefinition(SERVICE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
		      RootBeanDefinition def = new RootBeanDefinition(ServiceAnnotationBeanPostProcessor.class);
		      def.setSource(source);
		      def.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		      beanDefs.add(registerPostProcessor(registry, def, SERVICE_ANNOTATION_PROCESSOR_BEAN_NAME));
		 }
		
		if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
		if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
		if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition();
			try {
				def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
						AnnotationConfigUtils.class.getClassLoader()));
			}
			catch (ClassNotFoundException ex) {
				throw new IllegalStateException(
						"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
			}
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		return beanDefs;
	}

	private static BeanDefinitionHolder registerPostProcessor(
			BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {

		definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		registry.registerBeanDefinition(beanName, definition);
		return new BeanDefinitionHolder(definition, beanName);
	}

	private static DefaultListableBeanFactory unwrapDefaultListableBeanFactory(BeanDefinitionRegistry registry) {
		if (registry instanceof DefaultListableBeanFactory) {
			return (DefaultListableBeanFactory) registry;
		}
		else if (registry instanceof GenericApplicationContext) {
			return ((GenericApplicationContext) registry).getDefaultListableBeanFactory();
		}
		else {
			return null;
		}
	}

	public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
		processCommonDefinitionAnnotations(abd, abd.getMetadata());
	}

	static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
		if (metadata.isAnnotated(Lazy.class.getName())) {
			abd.setLazyInit(attributesFor(metadata, Lazy.class).getBoolean("value"));
		}
		else if (abd.getMetadata() != metadata && abd.getMetadata().isAnnotated(Lazy.class.getName())) {
			abd.setLazyInit(attributesFor(abd.getMetadata(), Lazy.class).getBoolean("value"));
		}

		if (metadata.isAnnotated(Primary.class.getName())) {
			abd.setPrimary(true);
		}
		if (metadata.isAnnotated(DependsOn.class.getName())) {
			abd.setDependsOn(attributesFor(metadata, DependsOn.class).getStringArray("value"));
		}

		if (abd instanceof AbstractBeanDefinition) {
			AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd;
			if (metadata.isAnnotated(Role.class.getName())) {
				absBd.setRole(attributesFor(metadata, Role.class).getNumber("value").intValue());
			}
			if (metadata.isAnnotated(Description.class.getName())) {
				absBd.setDescription(attributesFor(metadata, Description.class).getString("value"));
			}
		}
	}

	static BeanDefinitionHolder applyScopedProxyMode(
			ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {

		ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
		if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
			return definition;
		}
		boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
		return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
	}

	static AnnotationAttributes attributesFor(AnnotatedTypeMetadata metadata, Class<?> annotationClass) {
		return attributesFor(metadata, annotationClass.getName());
	}

	static AnnotationAttributes attributesFor(AnnotatedTypeMetadata metadata, String annotationClassName) {
		return AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(annotationClassName, false));
	}

	static Set<AnnotationAttributes> attributesForRepeatable(AnnotationMetadata metadata,
			Class<?> containerClass, Class<?> annotationClass) {

		return attributesForRepeatable(metadata, containerClass.getName(), annotationClass.getName());
	}

	@SuppressWarnings("unchecked")
	static Set<AnnotationAttributes> attributesForRepeatable(AnnotationMetadata metadata,
			String containerClassName, String annotationClassName) {

		Set<AnnotationAttributes> result = new LinkedHashSet<AnnotationAttributes>();
		addAttributesIfNotNull(result, metadata.getAnnotationAttributes(annotationClassName, false));

		Map<String, Object> container = metadata.getAnnotationAttributes(containerClassName, false);
		if (container != null && container.containsKey("value")) {
			for (Map<String, Object> containedAttributes : (Map<String, Object>[]) container.get("value")) {
				addAttributesIfNotNull(result, containedAttributes);
			}
		}
		return Collections.unmodifiableSet(result);
	}

	private static void addAttributesIfNotNull(Set<AnnotationAttributes> result, Map<String, Object> attributes) {
		if (attributes != null) {
			result.add(AnnotationAttributes.fromMap(attributes));
		}
	}

}

3.测试类

先使用jetty启动web服务,再通过客户端调用

ServerRunner.java

package cn.slimsmart.spring.rpc.annotation.demo;

import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.webapp.WebAppContext;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * 使用jetty作为服务端,运行测试前,先启动startWebapp
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext-test.xml"})
public class ServerRunner {
	private static Server server;

	@BeforeClass
	public static void startWebapp() throws Exception {
		server = new Server();
		Connector connector = new SelectChannelConnector();
		connector.setPort(8080); //设置webapp端口
		server.addConnector(connector);
		WebAppContext webAppContext = new WebAppContext();
		//设置工程名称
		webAppContext.setContextPath("/remoting");
		//这是webapp目录
		webAppContext.setWar("src/main/webapp");
		server.setHandler(webAppContext);
		server.start();
		System.out.println("syetem start sucess.");
	}

	@AfterClass
	public static void stopWebapp() throws Exception {
		server.stop();
	}
}
UserServiceTest.java

package cn.slimsmart.spring.rpc.annotation.demo;

import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * UserService测试类
 */
public class UserServiceTest extends ServerRunner{
	@Autowired
	private UserService userService;
	
	@Test
	  public void getUser() {
	    System.out.println(userService.getUser("slim"));
	  }
}
参考: http://my.oschina.net/damihui/blog/354055
参考代码: https://git.oschina.net/damivip/spring-remoting-annotation

你可能感兴趣的:(spring,rpc)