1. 程式人生 > >基於反射機制的服務代理呼叫

基於反射機制的服務代理呼叫

實現原理:通過傳遞服務bean的名稱、執行的方法及引數,通過反射機制進行呼叫返回。

優點:只需對外提供一個介面服務即可,只要容器中操作服務bean,通過介面即可呼叫,增加服務bean無需增加對外介面。

程式碼如下:

介面類

public interface ProxyService {
    /**
	 * webservice呼叫代理
	 * @param beanName  bean或類名
	 * @param functionName 呼叫的函式名
	 * @param params 引數
	 * @return
	 * @throws Exception
	 */
	Object proxy(String beanName, String functionName,String... params) throws Exception;
}
實現類:

服務基於spring,為了方便獲取服務bean,實現類實現spring的ApplicationContextAware介面

@Service
public class ProxyServiceImpl implements ProxyService ,ApplicationContextAware{

	protected final Logger logger = LoggerFactory.getLogger(getClass());
	
	@Resource
	private ApplicationContext applicationContext;

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}
	
	/**
	 * 通過代理執行業務方法,方法資料
	 */
	@SuppressWarnings("rawtypes")
	@Override
	public Object proxy(String beanName, String functionName, String... params) throws ServiceException {

		 //引數判斷
		 if(StringUtils.isEmpty(beanName)){
			 throw new Exception("error: beanName is empty.");
		 }
		 if(StringUtils.isEmpty(functionName)){
			 throw new Exception("error: functionName is empty.");
		 }
		 //獲取服務bean
		 Object bean = getBean(beanName);
		 if(bean == null){
			 throw new Exception("error: bean is not exist.");
		 }
		if(params == null || params.length ==0){
			logger.warn("proxy  params is empty.");
		}
		
		Method method = null;
		//處理無引數呼叫
		if(params == null || params.length ==0){
			 try {
				//獲取服務bean方法
				method = bean.getClass().getMethod(functionName);
			} catch (SecurityException e) {
				logger.error("proxy getMethod SecurityException:"+e.getMessage());
				e.printStackTrace();
			} catch (Exception e) {
				logger.error("proxy invoke IllegalArgumentException:"+e.getMessage());
				e.printStackTrace();
				throw new Exception("error: get method Exception:"+e.getMessage());
			} 
		}else{
			  //處理有引數呼叫
			  //處理呼叫方法引數
			  Class[] paraTypes = new Class[params.length];
		      for (int i = 0; i < paraTypes.length; i++) {
		        paraTypes[i] = String.class;
		      }
		    try {
				//獲取服務bean方法
				method = bean.getClass().getMethod(functionName, paraTypes);
			}catch (Exception e) {
				logger.error("proxy invoke IllegalArgumentException:"+e.getMessage());
				e.printStackTrace();
				throw new Exception("error: get method Exception:"+e.getMessage());
			} 
		}
		if(method == null ){
			throw new Exception("error: function is not exist.");
		}
	     
	     Object rs = null;
		try {
			//呼叫返回資料
			rs = method.invoke(bean,params);
		} catch (Exception e) {
			logger.error("proxy invoke IllegalArgumentException:"+e.getMessage());
			e.printStackTrace();
			throw new Exception("error: invoke method Exception:"+e.getMessage());
			
		} 
	    return rs;
	}
	
	/**
	 * 獲取bean物件
	 * @param beanName
	 * @return
	 */
	private Object getBean(String beanName){
		Object bean = null;
		bean = applicationContext.getBean(beanName);
		if(bean == null){
			try {
				Class<?> classe = Class.forName(beanName);
				bean = classe.newInstance();
			} catch (InstantiationException e) {
				logger.error("getBean InstantiationException:"+e.getMessage());
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				logger.error("getBean IllegalAccessException:"+e.getMessage());
				e.printStackTrace();
			}catch ( ClassNotFoundException e) {
				logger.error("getBean ClassNotFoundException:"+e.getMessage());
				e.printStackTrace();
			}
		}
		logger.debug("getBean(),beanName:"+beanName);
		return bean;
	}

}

呼叫方式如下:

proxyService.proxy("testservice","say","helloword");
testservice 為spring中bean例項
say 為testservice的業務方法
helloword 為引數

以上方式可以使用與遠端呼叫(如webservice等),對外為的代理呼叫介面。只需實現一個對外介面,呼叫服務內部多個業務服務。