/** * Dianping.com Inc. * Copyright (c) 2003-2013 All Rights Reserved. */ package com.dianping.pigeon.remoting.invoker.config.spring; import java.util.HashMap; import java.util.List; import java.util.Map; import com.dianping.pigeon.remoting.common.codec.SerializerType; import com.dianping.pigeon.remoting.common.domain.CallMethod; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.ReflectionToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; import org.springframework.beans.factory.FactoryBean; import com.dianping.pigeon.config.ConfigManager; import com.dianping.pigeon.config.ConfigManagerLoader; import com.dianping.pigeon.log.Logger; import com.dianping.pigeon.log.LoggerLoader; import com.dianping.pigeon.remoting.ServiceFactory; import com.dianping.pigeon.remoting.common.util.Constants; import com.dianping.pigeon.remoting.invoker.concurrent.InvocationCallback; import com.dianping.pigeon.remoting.invoker.config.InvokerConfig; import com.dianping.pigeon.remoting.invoker.config.InvokerMethodConfig; import com.dianping.pigeon.remoting.invoker.route.balance.LoadBalance; import com.dianping.pigeon.remoting.invoker.route.balance.LoadBalanceManager; import com.dianping.pigeon.remoting.invoker.route.region.RegionPolicyManager; import com.dianping.pigeon.util.ClassUtils; import com.dianping.pigeon.util.CollectionUtils; public class ReferenceBean implements FactoryBean { private ConfigManager configManager = ConfigManagerLoader.getConfigManager(); private static final Logger logger = LoggerLoader.getLogger(ReferenceBean.class); private String url; private String interfaceName; private String serialize = SerializerType.HESSIAN.getName(); private String callType = CallMethod.SYNC.getName(); private String cluster = Constants.CLUSTER_FAILFAST; private String vip; private int retries = 1; private boolean timeoutRetry; private int timeout = configManager.getIntValue(Constants.KEY_INVOKER_TIMEOUT, Constants.DEFAULT_INVOKER_TIMEOUT); private Object obj; private Class<?> objType; private InvocationCallback callback; private String version; private String protocol; private List<InvokerMethodConfig> methods; private ClassLoader classLoader; private String secret; private String remoteAppKey; private Object mock; public Object getMock() { return mock; } public void setMock(Object mock) { this.mock = mock; } public String getSecret() { return secret; } public void setSecret(String secret) { this.secret = secret; } public ClassLoader getClassLoader() { return classLoader; } public void setClassLoader(ClassLoader classLoader) { this.classLoader = classLoader; } public List<InvokerMethodConfig> getMethods() { return methods; } public void setMethods(List<InvokerMethodConfig> methods) { this.methods = methods; } public String getProtocol() { return protocol; } public void setProtocol(String protocol) { this.protocol = protocol; } public void setVersion(String version) { this.version = version; } private String suffix = configManager.getGroup(); private String loadBalance = LoadBalanceManager.DEFAULT_LOADBALANCE; private String regionPolicy = RegionPolicyManager.INSTANCE.DEFAULT_REGIONPOLICY; private Class<? extends LoadBalance> loadBalanceClass; /** * @deprecated */ private LoadBalance loadBalanceObj; /** * 是否对写Buffer限制大小(对于channel使用到的queue buffer的大小限制, 避免OutOfMemoryError) */ private boolean writeBufferLimit = configManager.getBooleanValue(Constants.KEY_DEFAULT_WRITE_BUFF_LIMIT, Constants.DEFAULT_WRITE_BUFF_LIMIT); public String getCluster() { return cluster; } public void setCluster(String cluster) { this.cluster = cluster; } public String getVip() { return vip; } public void setVip(String vip) { this.vip = vip; } public String getLoadBalance() { return loadBalance; } public int getRetries() { return retries; } public void setRetries(int retries) { this.retries = retries; } public boolean isTimeoutRetry() { return timeoutRetry; } public void setTimeoutRetry(boolean timeoutRetry) { this.timeoutRetry = timeoutRetry; } public Object getObject() { return this.obj; } public Class<?> getObjectType() { return this.objType; } public boolean isSingleton() { return true; } /** * @param url the url to set */ public void setUrl(String url) { this.url = url; } public void setCallType(String callType) { this.callType = callType; } /** * @param timeout the timeout to set */ public void setTimeout(int timeout) { this.timeout = timeout; } public void setInterfaceName(String interfaceName) { this.interfaceName = interfaceName; } /** * @param serialize the serialize to set */ public void setSerialize(String serialize) { this.serialize = serialize; } /** * @param callback the callback to set */ public void setCallback(InvocationCallback callback) { this.callback = callback; } /** * @param suffix the group to set */ public void setSuffix(String suffix) { this.suffix = suffix; } public void setLoadBalance(String loadBalance) { this.loadBalance = loadBalance; } public void setLoadBalanceClass(Class<? extends LoadBalance> loadBalanceClass) { this.loadBalanceClass = loadBalanceClass; } public void setLoadBalanceObj(LoadBalance loadBalanceObj) { this.loadBalanceObj = loadBalanceObj; } public void setWriteBufferLimit(boolean writeBufferLimit) { this.writeBufferLimit = writeBufferLimit; } public String getRegionPolicy() { return regionPolicy; } public void setRegionPolicy(String regionPolicy) { this.regionPolicy = regionPolicy; } public String getRemoteAppKey() { return remoteAppKey; } public void setRemoteAppKey(String remoteAppKey) { this.remoteAppKey = remoteAppKey; } public void init() throws Exception { if (StringUtils.isBlank(interfaceName)) { throw new IllegalArgumentException("invalid interface:" + interfaceName); } this.objType = ClassUtils.loadClass(this.classLoader, this.interfaceName.trim()); InvokerConfig<?> invokerConfig = new InvokerConfig(this.objType, this.url, this.timeout, this.callType, this.serialize, this.callback, this.suffix, this.writeBufferLimit, this.loadBalance, this.cluster, this.retries, this.timeoutRetry, this.vip, this.version, this.protocol); invokerConfig.setClassLoader(classLoader); invokerConfig.setSecret(secret); invokerConfig.setRegionPolicy(regionPolicy); if (!CollectionUtils.isEmpty(methods)) { Map<String, InvokerMethodConfig> methodMap = new HashMap<String, InvokerMethodConfig>(); invokerConfig.setMethods(methodMap); for (InvokerMethodConfig method : methods) { methodMap.put(method.getName(), method); } } checkMock(); // 降级配置检查 invokerConfig.setMock(mock); checkRemoteAppkey(); invokerConfig.setRemoteAppKey(remoteAppKey); this.obj = ServiceFactory.getService(invokerConfig); configLoadBalance(invokerConfig); } private void checkMock() throws Exception { if (mock != null) { // 检查是否实现了interface if (!objType.isAssignableFrom(mock.getClass())) { throw new IllegalStateException("The mock implemention class " + mock.getClass().getName() + " not implement interface " + objType.getName()); } } } private void checkRemoteAppkey() { if (configManager.getBooleanValue("pigeon.remote.appkey.check.exist", true)) { if (StringUtils.isNotBlank(remoteAppKey)) { remoteAppKey = ""; logger.info("set remoteAppKey to blank"); } } } private void configLoadBalance(InvokerConfig invokerConfig) { Object loadBalanceToSet = loadBalanceObj != null ? loadBalanceObj : (loadBalanceClass != null ? loadBalanceClass : (loadBalance != null ? loadBalance : null)); if (loadBalanceToSet != null) { LoadBalanceManager.register(invokerConfig.getUrl(), suffix, loadBalanceToSet); } } @Override public String toString() { return ReflectionToStringBuilder.toString(this, ToStringStyle.SHORT_PREFIX_STYLE); } }