标签:
服务端配置
1、注解定义
package org.springframework.remoting;
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;
/**
* 在类上声明
*
* @author gaowenming
*
*/
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface RemoteService {
ServiceType serviceType() default ServiceType.HTTP;
Class<?> serviceInterface();
}
2、服务发布类型
package org.springframework.remoting;
/**
* 远程调用类型
*
* @author gaowenming
*
*/
public enum ServiceType {
HTTP, BURLAP, HESSIAN, RMI
}
3、RMI发布接口设置
package org.springframework.remoting;
import org.springframework.stereotype.Component;
import java.lang.annotation.*;
import java.rmi.registry.Registry;
/**
* RMI默认是1099端口,可以配置
*
* @author gaowenming
*
*/
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface RmiServiceProperty {
int registryPort() default Registry.REGISTRY_PORT;
}
4、注解标签解析
package org.springframework.beans.factory.annotation;
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.RemoteService;
import org.springframework.remoting.RmiServiceProperty;
import org.springframework.remoting.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;
import java.rmi.RemoteException;
/**
* 解析注解
*
* @author gaowenming
*
*/
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) {
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;
} 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;
} 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;
} 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 Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
public void setOrder(int order) {
this.order = order;
}
@Override
public int getOrder() {
return order;
}
}
5、重写AnnotationConfigUtils,必须与原类在同一目录
/*
* Copyright 2002-2012 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.LinkedHashSet;
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.annotation.ServiceAnnotationBeanPostProcessor;
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.RootBeanDefinition;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.ClassUtils;
import static org.springframework.context.annotation.MetadataUtils.*;
/**
* 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.
*
* @author Mark Fisher
* @author Juergen Hoeller
* @author Chris Beams
* @since 2.5
* @see CommonAnnotationBeanPostProcessor
* @see org.springframework.context.annotation.ConfigurationClassPostProcessor
* @see org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
* @see org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor
* @see org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor
*/
public class AnnotationConfigUtils {
public static final String SERVICE_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.beans.factory.annotation.serviceAnnotationBeanPostProcessor";
/**
* The bean name of the internally managed Configuration annotation processor.
*/
public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalConfigurationAnnotationProcessor";
/**
* 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 Scheduled annotation processor.
*/
public static final String SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalScheduledAnnotationProcessor";
/**
* The bean name of the internally managed Async annotation processor.
*/
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.
*/
public static final String ASYNC_EXECUTION_ASPECT_BEAN_NAME =
"org.springframework.scheduling.config.internalAsyncExecutionAspect";
/**
* The class name of the AspectJ async execution aspect.
*/
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.
*/
public static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME =
"org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";
/**
* The bean name of the internally managed cache advisor.
*/
public static final String CACHE_ADVISOR_BEAN_NAME =
"org.springframework.cache.config.internalCacheAdvisor";
/**
* The bean name of the internally managed cache aspect.
*/
public static final String CACHE_ASPECT_BEAN_NAME =
"org.springframework.cache.config.internalCacheAspect";
/**
* The class name of the AspectJ caching aspect.
*/
public static final String CACHE_ASPECT_CLASS_NAME =
"org.springframework.cache.aspectj.AnnotationCacheAspect";
/**
* The name of the AspectJ caching aspect @{@code Configuration} class.
*/
public static final String CACHE_ASPECT_CONFIGURATION_CLASS_NAME =
"org.springframework.cache.aspectj.AspectJCachingConfiguration";
/**
* 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";
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</code>.
* @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) {
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);
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 {
ClassLoader cl = AnnotationConfigUtils.class.getClassLoader();
def.setBeanClass(cl.loadClass(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME));
}
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);
}
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
AnnotationMetadata metadata = abd.getMetadata();
if (metadata.isAnnotated(Primary.class.getName())) {
abd.setPrimary(true);
}
if (metadata.isAnnotated(Lazy.class.getName())) {
abd.setLazyInit(attributesFor(metadata, Lazy.class).getBoolean("value"));
}
if (metadata.isAnnotated(DependsOn.class.getName())) {
abd.setDependsOn(attributesFor(metadata, DependsOn.class).getStringArray("value"));
}
if (abd instanceof AbstractBeanDefinition) {
if (metadata.isAnnotated(Role.class.getName())) {
Integer role = attributesFor(metadata, Role.class).getNumber("value");
((AbstractBeanDefinition)abd).setRole(role);
}
}
}
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);
}
}
6、接口定义
package org.spring.remote.hessian;
/**
* Description: <类功能描述>. <br>
* <p>
* <使用说明>
* </p>
* Makedate:2015年6月25日 下午4:32:57
*
* @author gaowenming
* @version V1.0
*/
public interface HessianService {
public void sayHello();
}
7、接口实现与发布
package org.spring.remote.hessian.impl;
import org.spring.remote.hessian.HessianService;
import org.springframework.remoting.RemoteService;
import org.springframework.remoting.ServiceType;
import org.springframework.stereotype.Service;
/**
* Description: <类功能描述>. <br>
*
* @Service : spring bean的声明,但是由于是远程调用的接口,所以必须斜杠开始
* @RemoteService : 远程调用的配置
*
* @author gaowenming
* @version V1.0
*/
@Service("/HessianService.service")
@RemoteService(serviceInterface = HessianService.class, serviceType = ServiceType.HESSIAN)
public class HessianServiceImpl implements HessianService {
@Override
public void sayHello() {
System.out.println("hello HessianService");
}
}
至此,服务端的服务就发布完成
客户端配置
1、定义服务
<?xml version="1.0" encoding="ISO-8859-1"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> <!--httpInvoker client --> <bean id="httpService" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean"> <property name="serviceUrl" value="http://localhost:8080/spring-remote/HttpService.service" /> <property name="serviceInterface" value="org.spring.remote.http.HttpService" /> </bean> <!--rmi client --> <bean id="rmiService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean"> <property name="serviceUrl" value="rmi://localhost:9000/RMIService.service" /> <property name="serviceInterface" value="org.spring.remote.rmi.RMIService" /> </bean> <!--hessian client --> <bean id="hessianService" class="org.springframework.remoting.caucho.HessianProxyFactoryBean"> <property name="serviceUrl" value="http://localhost:8080/spring-remote/HessianService.service" /> <property name="serviceInterface" value="org.spring.remote.hessian.HessianService" /> </bean> <!--burlap client --> <bean id="burlapService" class="org.springframework.remoting.caucho.BurlapProxyFactoryBean"> <property name="serviceUrl" value="http://localhost:8080/spring-remote/BurlapService.service" /> <property name="serviceInterface" value="org.spring.remote.burlap.BurlapService" /> </bean> </beans>
2、测试服务
package org.smart.remote_client;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.spring.remote.hessian.HessianService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* Description: <类功能描述>. <br>
* <p>
* <使用说明>
* </p>
* Makedate:2015年6月25日 下午4:48:30
*
* @author gaowenming
* @version V1.0
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext-remote.xml" })
public class HessianServiceTest {
@Autowired
private HessianService hessianService;
@Test
public void test() {
hessianService.sayHello();
}
}
标签:
原文地址:http://my.oschina.net/gaowm/blog/471078