package com.dounine.corgi.rpc.spring;
import com.dounine.corgi.cluster.Balance;
import com.dounine.corgi.cluster.CirculationBalance;
import com.dounine.corgi.cluster.ClusterPaths;
import com.dounine.corgi.register.api.*;
import com.dounine.corgi.rpc.RpcApp;
import com.dounine.corgi.rpc.listen.RpcContainer;
import com.dounine.corgi.rpc.protocol.CorgiProtocol;
import com.dounine.corgi.rpc.protocol.IProtocol;
import com.dounine.corgi.rpc.spring.annotation.Reference;
import com.dounine.corgi.rpc.spring.annotation.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
/**
* Created by huanghuanlai on 2016/10/18.
*/
public class SpringProcessor implements BeanPostProcessor,ApplicationListener,IRpc {
private static final Logger LOGGER = LoggerFactory.getLogger(SpringProcessor.class);
protected static String hostName = null;
private static final List<String> REGISTER_API_INTERFACES = new ArrayList<>();
static {
try {
hostName = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
@Autowired
protected Environment env;
@Autowired
protected Register register;
@Autowired
protected IProtocol protocol;
@Autowired
protected Balance balance;
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (checkRpcService(bean)) {
registerObject(bean);
}
reflectProxyReference(bean);
return bean;
}
public boolean checkRpcService(Object bean) {
return bean.getClass().isAnnotationPresent(Service.class);
}
public void reflectProxyReference(Object bean){
Class<?> cls = bean.getClass();
for (Field field : cls.getDeclaredFields()) {
if (field.isAnnotationPresent(Reference.class)) {
boolean oldAcc = field.isAccessible();
field.setAccessible(true);
try {
field.set(bean, RpcApp.instance().getProxy(field.getType(),field.getAnnotation(Reference.class),balance));
field.setAccessible(oldAcc);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
public void registerObject(Object bean) {
for (Class interfac : bean.getClass().getInterfaces()) {
String apiClass = interfac.getName().replace(".","/");
register.register(new DefaultRegNode(nodeInfo(),"/"+apiClass));
}
}
public String nodeInfo() {
return hostName+":" + protocol.getPort();
}
@Override
@Bean
public Register getRegister() {
String protocol = env.getProperty("corgi.register.protocol","p2p");
Register reg = getP2PRegister();
if("zookeeper".equals(protocol)){
reg = getZkRegister();
}
return reg;
}
public ZkRegister getZkRegister(){
ZkRegister registerConfig = new ZkRegister();
registerConfig.setAddress(env.getProperty("corgi.register.address","localhost:2181"));
registerConfig.setTimeout(env.getProperty("corgi.register.timeout",Integer.class,3000));
return registerConfig;
}
public P2PRegister getP2PRegister(){
P2PRegister registerConfig = new P2PRegister();
registerConfig.setAddress(env.getProperty("corgi.register.address","localhost:7777"));
registerConfig.setTimeout(env.getProperty("corgi.register.timeout",Integer.class,3000));
return registerConfig;
}
@Override
@Bean
public Balance getBalance() {
String protocol = env.getProperty("corgi.register.protocol","p2p");
ClusterPaths paths = null;
if("zookeeper".equals(protocol)){
paths = new ZkClusterPaths(getZkRegister());
}else if("p2p".equals(protocol)){
paths = new P2PClusterPaths(getP2PRegister());
}
return new CirculationBalance(paths);
}
@Override
@Bean
public IProtocol getProtocol(){
CorgiProtocol corgiProtocol = new CorgiProtocol();
corgiProtocol.setName(env.getProperty("corgi.protocol.name","corgi"));
corgiProtocol.setPort(env.getProperty("corgi.protocol.port",Integer.class,7777));
return corgiProtocol;
}
@Override
public void onApplicationEvent(ApplicationEvent event) {
if(!RpcContainer.isListener()){
RpcApp.init(getProtocol(),env.getProperty("corgi.application.name")).export();
}
}
}