原来的配置
<bean name="/UserService" class="org.springframework.remoting.caucho.HessianServiceExporter"> <property name="serviceInterface" value="com.snailteam.service.UserService"></property> <property name="service" ref="userServiceImp"></property> </bean>
<bean class="org.springframework.remoting.caucho.HessianProxyFactoryBean"> <property name="serviceUrl" value="http://localhost:8080/api/service/UserService"></property> <property name="serviceInterface" value="com.snailteam.rpc.service.UserService"></property> </bean>
现在的配置
<bean class="org.springframework.remoting.caucho.HessianExporterMapperScannerConfigurer"> <property name="basePackage" value="com.snailteam.service" /> </bean>
<bean class="org.springframework.remoting.caucho.HessianProxyMapperScannerConfigurer"> <property name="serviceUrl" value="http://localhost:8080/api/service"></property> <property name="debug" value="false"></property> <property name="connectTimeout" value="3000"></property> <property name="readTimeout" value="30000"></property> <property name="basePackage" value="com.snailteam.rpc" /> </bean>
代码
/** * @author [email protected] * */ package org.springframework.remoting.caucho; import java.io.IOException; import java.lang.annotation.Annotation; import java.util.HashMap; import java.util.Map; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; 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.ClassPathBeanDefinitionScanner; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.classreading.SimpleMetadataReaderFactory; import org.springframework.core.type.filter.AnnotationTypeFilter; import org.springframework.core.type.filter.AssignableTypeFilter; import org.springframework.core.type.filter.TypeFilter; import org.springframework.util.StringUtils; import org.springframework.web.context.support.XmlWebApplicationContext; /** * @author [email protected] * @see Mybatis-spring MapperScannerConfigurer */ public class HessianExporterMapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware { protected final Logger logger = LoggerFactory.getLogger(getClass()); private String serviceUrl; private String basePackage; private boolean debug; private ApplicationContext applicationContext; private Class<? extends Annotation> annotationClass; private Class<?> markerInterface; private String beanName; private Map<String, String> implClassContextName = new HashMap<String, String>(); public void setDebug(boolean debug) { this.debug = debug; } public void setImplClassContextName(Map<String, String> implClassContextName) { this.implClassContextName = implClassContextName; } public Map<String, String> getImplClassContextName() { return implClassContextName; } public void setApplicationContext(ApplicationContext applicationContext) { this.applicationContext = applicationContext; } public void setBasePackage(String basePackage) { this.basePackage = basePackage; } public void setServiceUrl(String serviceUrl) { this.serviceUrl = serviceUrl; } public void setAnnotationClass(Class<? extends Annotation> annotationClass) { this.annotationClass = annotationClass; } public void setMarkerInterface(Class<?> markerInterface) { this.markerInterface = markerInterface; } @Override public void postProcessBeanFactory( ConfigurableListableBeanFactory beanFactory) throws BeansException { } @Override public void postProcessBeanDefinitionRegistry( BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException { Scanner scanner = new Scanner(beanDefinitionRegistry); scanner.setResourceLoader(this.applicationContext); scanner.setBeanNameGenerator(new BeanNameGenerator() { @Override public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) { String beanName = definition.getBeanClassName().substring( definition.getBeanClassName().lastIndexOf(".") + 1); return "/" + beanName; } }); scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS)); } private final class Scanner extends ClassPathBeanDefinitionScanner { public Scanner(BeanDefinitionRegistry registry) { super(registry); } protected Set<BeanDefinitionHolder> doScan(String... basePackages) { Set<BeanDefinitionHolder> beanDefinitions = super .doScan(basePackages); if (beanDefinitions.isEmpty()) { logger.warn("No R mapper was found in '" + HessianExporterMapperScannerConfigurer.this.basePackage + "' package. Please check your configuration."); } else { for (BeanDefinitionHolder holder : beanDefinitions) { GenericBeanDefinition definition = (GenericBeanDefinition) holder .getBeanDefinition(); if (logger.isDebugEnabled()) { logger.debug("Creating MapperFactoryBean with name '" + holder.getBeanName() + "' and '" + definition.getBeanClassName() + "' mapperInterface"); } /** */ try { //解析扫描的类 Class cls = definition.resolveBeanClass(this.getResourceLoader().getClassLoader()); definition.getPropertyValues().add("serviceInterface", definition.getBeanClassName()); //通过class type,在spring root applaction获取对应的bean名字,取第一个。 definition.getPropertyValues().add("service",new RuntimeBeanReference(applicationContext.getParent().getBeanNamesForType(cls)[0])); definition.setBeanClass(HessianServiceExporter.class); } catch (ClassNotFoundException e) { logger.error(e); } } } return beanDefinitions; } @Override protected boolean isCandidateComponent( AnnotatedBeanDefinition beanDefinition) { return (beanDefinition.getMetadata().isInterface() && beanDefinition .getMetadata().isIndependent()); } @Override protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException { if (super.checkCandidate(beanName, beanDefinition)) { return true; } else { logger.warn("Skipping HessianProxyFactoryBean with name '" + beanName + "' and '" + beanDefinition.getBeanClassName() + "' mapperInterface" + ". Bean already defined with the same name!"); return false; } } @Override protected void registerDefaultFilters() { boolean acceptAllInterfaces = true; // if specified, use the given annotation and / or marker interface if (HessianExporterMapperScannerConfigurer.this.annotationClass != null) { addIncludeFilter(new AnnotationTypeFilter( HessianExporterMapperScannerConfigurer.this.annotationClass)); acceptAllInterfaces = false; } // override AssignableTypeFilter to ignore matches on the actual // marker interface if (HessianExporterMapperScannerConfigurer.this.markerInterface != null) { addIncludeFilter(new AssignableTypeFilter( HessianExporterMapperScannerConfigurer.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"); } }); } } @Override public void setBeanName(String name) { } @Override public void afterPropertiesSet() throws Exception { } }
package org.springframework.remoting.caucho; import static org.springframework.util.Assert.notNull; import java.io.IOException; import java.lang.annotation.Annotation; import java.util.Set; 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.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.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.Assert; import org.springframework.util.StringUtils; /** * @author [email protected] * @see Mybatis-spring MapperScannerConfigurer */ public class HessianProxyMapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware { private String serviceUrl; private String basePackage; private boolean debug; private Integer connectTimeout; private Integer readTimeout; private ApplicationContext applicationContext; private Class<? extends Annotation> annotationClass; private Class<?> markerInterface; private String beanName; public void setConnectTimeout(Integer connectTimeout) { this.connectTimeout = connectTimeout; } public void setDebug(boolean debug) { this.debug = debug; } public void setReadTimeout(Integer readTimeout) { this.readTimeout = readTimeout; } public void setApplicationContext(ApplicationContext applicationContext) { this.applicationContext = applicationContext; } public void setBasePackage(String basePackage) { this.basePackage = basePackage; } public void setServiceUrl(String serviceUrl) { this.serviceUrl = serviceUrl; } public void setAnnotationClass(Class<? extends Annotation> annotationClass) { this.annotationClass = annotationClass; } public void setMarkerInterface(Class<?> markerInterface) { this.markerInterface = markerInterface; } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { } @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException { Scanner scanner = new Scanner(beanDefinitionRegistry); scanner.setResourceLoader(this.applicationContext); scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS)); } /** * org.springframework.remoting.caucho.HessianProxyFactoryBean */ private final class Scanner extends ClassPathBeanDefinitionScanner { public Scanner(BeanDefinitionRegistry registry) { super(registry); } protected Set<BeanDefinitionHolder> doScan(String... basePackages) { Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages); if (beanDefinitions.isEmpty()) { logger.warn("No R mapper was found in '" + HessianProxyMapperScannerConfigurer.this.basePackage + "' package. Please check your configuration."); } else { for (BeanDefinitionHolder holder : beanDefinitions) { GenericBeanDefinition definition = (GenericBeanDefinition) holder.getBeanDefinition(); if (logger.isDebugEnabled()) { logger.debug("Creating MapperFactoryBean with name '" + holder.getBeanName() + "' and '" + definition.getBeanClassName() + "' mapperInterface"); } /** <bean class="org.springframework.remoting.caucho.HessianProxyFactoryBean"> <property name="serviceUrl" value="http://localhost:8080/api/service/UserService"></property> <property name="serviceInterface" value="com.snailteam.rpc.service.UserService"></property> </bean> */ definition.getPropertyValues().add("serviceInterface", definition.getBeanClassName()); String beanName = definition.getBeanClassName().substring(definition.getBeanClassName().lastIndexOf(".")+1); Assert.notNull(serviceUrl, "HessianProxyMapperScannerConfigurer serviceUrl must not be null"); definition.setBeanClass(HessianProxyFactoryBean.class); definition.getPropertyValues().add("serviceUrl", HessianProxyMapperScannerConfigurer.this.serviceUrl+"/"+beanName); definition.getPropertyValues().add("debug", HessianProxyMapperScannerConfigurer.this.debug); definition.getPropertyValues().add("readTimeout", HessianProxyMapperScannerConfigurer.this.readTimeout); // serviceInterface } } return beanDefinitions; } @Override protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { return (beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent()); } @Override protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException { if (super.checkCandidate(beanName, beanDefinition)) { return true; } else { logger.warn("Skipping HessianProxyFactoryBean with name '" + beanName + "' and '" + beanDefinition.getBeanClassName() + "' mapperInterface" + ". Bean already defined with the same name!"); return false; } } @Override protected void registerDefaultFilters() { boolean acceptAllInterfaces = true; // if specified, use the given annotation and / or marker interface if (HessianProxyMapperScannerConfigurer.this.annotationClass != null) { addIncludeFilter(new AnnotationTypeFilter(HessianProxyMapperScannerConfigurer.this.annotationClass)); acceptAllInterfaces = false; } // override AssignableTypeFilter to ignore matches on the actual // marker interface if (HessianProxyMapperScannerConfigurer.this.markerInterface != null) { addIncludeFilter(new AssignableTypeFilter(HessianProxyMapperScannerConfigurer.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"); } }); } } @Override public void setBeanName(String name) { this.beanName = name; } @Override public void afterPropertiesSet() throws Exception { notNull(this.basePackage, "Property 'basePackage' is required"); } }
package org.springframework.remoting.caucho; /** * @author [email protected] * @version 创建时间:2017-2-14 下午6:18:59 * 类说明 */ import java.lang.reflect.Field; import org.springframework.aop.framework.AdvisedSupport; import org.springframework.aop.framework.AopProxy; import org.springframework.aop.support.AopUtils; public class AopTargetUtils { /** * 获取 目标对象 * * @param proxy * 代理对象 * @return * @throws Exception */ public static Object getTarget(Object proxy) throws Exception { if (!AopUtils.isAopProxy(proxy)) { return proxy;// 不是代理对象 } if (AopUtils.isJdkDynamicProxy(proxy)) { return getJdkDynamicProxyTargetObject(proxy); } else { // cglib return getCglibProxyTargetObject(proxy); } } private static Object getCglibProxyTargetObject(Object proxy) throws Exception { Field h = proxy.getClass().getDeclaredField("CGLIB$CALLBACK_0"); h.setAccessible(true); Object dynamicAdvisedInterceptor = h.get(proxy); Field advised = dynamicAdvisedInterceptor.getClass().getDeclaredField("advised"); advised.setAccessible(true); Object target = ((AdvisedSupport) advised.get(dynamicAdvisedInterceptor)).getTargetSource().getTarget(); return target; } private static Object getJdkDynamicProxyTargetObject(Object proxy) throws Exception { Field h = proxy.getClass().getSuperclass().getDeclaredField("h"); h.setAccessible(true); AopProxy aopProxy = (AopProxy) h.get(proxy); Field advised = aopProxy.getClass().getDeclaredField("advised"); advised.setAccessible(true); Object target = ((AdvisedSupport) advised.get(aopProxy)).getTargetSource().getTarget(); return target; } }