rmi通過springboot註解方式實現自動釋出服務和代理實現類
阿新 • • 發佈:2019-02-11
一、服務的釋出:
1、原理:通過註解註釋要釋出服務的實現類,修改spring的註解掃描工具,當掃描到一個指定的註解就釋出一個rmi服務。
2、spring釋出rmi服務的程式碼:
RmiServiceExporter rmiExporter = new RmiServiceExporter();
rmiExporter.setService(bean);//注入要釋出的service的bean
rmiExporter.setServiceName(“DateRemoteService”);
rmiExporter.setServiceInterface(DateRemote.class);
rmiExporter.setRegistryPort(1199);//不設定預設為埠1099
hessianServiceExporter.afterPropertiesSet();
3、實現,需要4個類,2個註解類,一個服務釋出類,一個spring工具類的替換類:
RemoteService,註解類,註釋在需要釋出的實現類上:
package com.yuntu.manager.base.annotation; import com.yuntu.manager.base.enumeration.ServiceType; import org.springframework.stereotype.Component; import java.lang.annotation.*; /** * * 使用這個標籤的實現類,將會在註冊一個由spring管理的rmi服務,服務名就是其指定的介面名稱。服務埠號是由RmiServiceProperty註釋指定 * Created by niuzy on 2018-09-19. */ @Target({ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface RemoteService { ServiceType serviceType() default ServiceType.RMI; Class<?> serviceInterface(); }
RmiServiceProperty 註釋類,指定釋出服務的埠,也可以更上面的註釋類合併
package com.yuntu.manager.base.annotation; import org.springframework.stereotype.Component; import java.lang.annotation.*; import java.rmi.registry.Registry; /** * 指定服務埠號 * Created by niuzy on 2018-09-19. */ @Target({ ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface RmiServiceProperty { int registryPort() default Registry.REGISTRY_PORT; }
ServiceAnnotationBeanPostProcessor,用於釋出rmi服務:
package com.yuntu.manager.base.core;
import com.yuntu.manager.base.annotation.RemoteService;
import com.yuntu.manager.base.annotation.RmiServiceProperty;
import com.yuntu.manager.base.enumeration.ServiceType;
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.caucho.HessianServiceExporter;
import org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter;
import org.springframework.remoting.rmi.RmiServiceExporter;
import java.rmi.RemoteException;
/**
* Created by niuzy on 2018-09-19.
*/
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) {
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 = service.serviceInterface().getSimpleName();
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;
}
}
AnnotationConfigUtils ,用於替換spring的AnnotationConfigUtils,注意包名。
package org.springframework.context.annotation;
import com.yuntu.manager.base.core.ServiceAnnotationBeanPostProcessor;
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.event.DefaultEventListenerFactory;
import org.springframework.context.event.EventListenerMethodProcessor;
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.lang.Nullable;
import org.springframework.util.ClassUtils;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
/**
* 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
* @author Stephane Nicoll
* @since 2.5
* @see ContextAnnotationAutowireCandidateResolver
* @see CommonAnnotationBeanPostProcessor
* @see ConfigurationClassPostProcessor
* @see AutowiredAnnotationBeanPostProcessor
* @see RequiredAnnotationBeanPostProcessor
*/
public class AnnotationConfigUtils {
/**
* The bean name of the internally managed Configuration annotation processor.
*/
public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.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 @EventListener annotation processor.
*/
public static final String EVENT_LISTENER_PROCESSOR_BEAN_NAME =
"org.springframework.context.event.internalEventListenerProcessor";
/**
* The bean name of the internally managed EventListenerFactory.
*/
public static final String EVENT_LISTENER_FACTORY_BEAN_NAME =
"org.springframework.context.event.internalEventListenerFactory";
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, @Nullable 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<>(4);
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));
}
/**
* 非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(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));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_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);
}
@Nullable
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) {
AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
if (lazy != null) {
abd.setLazyInit(lazy.getBoolean("value"));
}
else if (abd.getMetadata() != metadata) {
lazy = attributesFor(abd.getMetadata(), Lazy.class);
if (lazy != null) {
abd.setLazyInit(lazy.getBoolean("value"));
}
}
if (metadata.isAnnotated(Primary.class.getName())) {
abd.setPrimary(true);
}
AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
if (dependsOn != null) {
abd.setDependsOn(dependsOn.getStringArray("value"));
}
if (abd instanceof AbstractBeanDefinition) {
AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd;
AnnotationAttributes role = attributesFor(metadata, Role.class);
if (role != null) {
absBd.setRole(role.getNumber("value").intValue());
}
AnnotationAttributes description = attributesFor(metadata, Description.class);
if (description != null) {
absBd.setDescription(description.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);
}
@Nullable
static AnnotationAttributes attributesFor(AnnotatedTypeMetadata metadata, Class<?> annotationClass) {
return attributesFor(metadata, annotationClass.getName());
}
@Nullable
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<>();
// Direct annotation present?
addAttributesIfNotNull(result, metadata.getAnnotationAttributes(annotationClassName, false));
// Container annotation present?
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 merged result
return Collections.unmodifiableSet(result);
}
private static void addAttributesIfNotNull(
Set<AnnotationAttributes> result, @Nullable Map<String, Object> attributes) {
if (attributes != null) {
result.add(AnnotationAttributes.fromMap(attributes));
}
}
}
4、使用:
package com.yuntu.manager.base.test;
import com.yuntu.manager.base.annotation.RemoteService;
import com.yuntu.manager.base.annotation.RmiServiceProperty;
import org.springframework.stereotype.Service;
/**
* Created by niuzy on 2018-09-19.
*/
@RemoteService(serviceInterface=RemoteServiceTest.class)
@RmiServiceProperty(registryPort = 1234)
@Service
public class RemoteServiceTestImpl implements RemoteServiceTest {
public String say(String word) throws Exception {
return word;
}
}