原来的配置
<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 xiaofancn@gmail.com
*
*/
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 xiaofancn@gmail.com
* @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 xiaofancn@gmail.com
* @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 xiaofancn@gmail.com
* @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;
}
}