1. 程式人生 > 程式設計 >在java中由類名和方法名字串實現其呼叫方式

在java中由類名和方法名字串實現其呼叫方式

js裡通過eval()函式,在知道某個方法名是可以實現呼叫該方法,那麼在java裡邊又怎麼實現的呢?

java裡邊是通過反射機制來實現,程式碼如下:

import java.lang.reflect.Method;
 
public class Test {
 public static void main(String[] args) throws Exception {
 String className = "com.runqianapp.ngr.alias.example.FunClass";
 String methodName = "sayHello";
 Class clz = Class.forName(className);
 // 
 Object obj = clz.newInstance();
 //獲取方法 
 Method m = obj.getClass().getDeclaredMethod(methodName,String.class);
 //呼叫方法 
 String result = (String) m.invoke(obj,"aaaaa");
 System.out.println(result);
 }
}
 
class FunClass{
 public String sayHello(String s){
 System.out.println(s);
 return "hello!";
 }
}

補充知識:一個controller呼叫根據不同業務分發不同service

在一個專案中需要寫很多的controller去呼叫不同的service,而寫一個閘道器可以省去寫controller層的痛苦。

下面開始介紹可以分發不同service。

1.因為service在專案啟動時就已全部注入到spring容器中,所以我們需要寫一個工具類,可以從spring上下文(applicationContext)中獲取到對應service

@Component
public class SpringUtil implements ApplicationContextAware {
 
 @Autowired
 private static ApplicationContext applicationContext;
 
 @Override
 public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  if (SpringUtil.applicationContext == null) {
   SpringUtil.applicationContext = applicationContext;
  }
  System.out.println("========ApplicationContext配置成功,在普通類可以通過呼叫SpringUtil.getAppContext()獲取applicationContext物件,applicationContext=" + SpringUtil.applicationContext + "========");
 }
 
 //獲取applicationContext
 public static ApplicationContext getApplicationContext() {
  return applicationContext;
 }
 
 //通過name獲取 Bean.
 public static Object getBean(String name) {
  return getApplicationContext().getBean(name);
 }
 
 //通過class獲取Bean.
 public static <T> T getBean(Class<T> clazz) {
  return getApplicationContext().getBean(clazz);
 }
 
 //通過name,以及Clazz返回指定的Bean
 public static <T> T getBean(String name,Class<T> clazz) {
  return getApplicationContext().getBean(name,clazz);
 }
}

2.上面的SpringUtil我們已經可以在上下文中直接取到對於的service了,下面就開始編寫controller進行請求的分發(我稱之為閘道器)。首先我們需要先寫一個抽象類,來定義service,這樣接下來的sevice只需要繼承這個抽象類即可(我們還可以寫一些時間統計,交易流水入庫等。。自我感覺很大的用處)。

public abstract class RootService { 
 private Logger logger = LoggerFactory.getLogger(RootService.class); 
 private long beforeTime; 
 private long endTime; 
 
 private void before (String action) {
  beforeTime = System.currentTimeMillis();
  logger.info("交易:" + action + "開始時間:" + beforeTime);
 }
 
 private void end (String action) {
  endTime = System.currentTimeMillis();
  long time = endTime - beforeTime;
  logger.info("交易:" + action + "結束時間:" + endTime);
  logger.info("交易:" + action + "耗時:" + time);
 }
 
 public JSONObject execute(String actionName,Map map) {
  before(actionName);
  JSONObject jsonObject = doNext(map);
  end(actionName);
  return jsonObject;
 }
 
 private JSONObject doNext(Map map) {
  try {
   return doAction(map);
  } catch (Exception e) {
   e.printStackTrace();
   JSONObject js = new JSONObject();
   js.put("retCode","000000");
   js.put("retMsg","程式報錯");
   return js;
  }
 } 
 protected abstract JSONObject doAction(Map map); 
}

3.一切準備就緒,我們可以開始編寫contrconoller了(閘道器)

@Controller
@RequestMapping("/root")
public class RootController {
 
 @ResponseBody
 @RequestMapping(value = "/h5.do",produces = {"application/json;charset=UTF-8"},method = RequestMethod.POST)
 public JSONObject root(@RequestBody Map<String,Object> map,HttpServletRequest httpServletRequest){
  String service = (String) map.get("service");
 
  JSONObject js = new JSONObject();
  RootService rootService = (RootService) SpringUtil.getBean(service);
 
  return rootService.execute(service,map);
 } 
}

到這裡一個閘道器就寫好了,然後我們寫一個service進行測試一下(對應的Dao層我就不現醜了,相信大家都會)

@Service
public class UserServiceImpl extends RootService{
 private Logger logger = LoggerFactory.getLogger(UserService.class);
 
 @Autowired
 private UserDao userDao;
 
 @Override
 protected JSONObject doAction(Map map) {
  JSONObject js = new JSONObject();
  String id = (String) map.get("id");
  User user = userDao.getUser(id);
  js.put("user",user);
  logger.info("進入了UserService");
  return js;
 }
}

下面我們用postman測試一下測試報文為:

{
 "id":"1","service":"userServiceImpl"
}

控制檯列印為:

2019-10-18 17:24:41.089 INFO 6452 --- [nio-8080-exec-2] c.s.s.service.util.RootService : 交易:userService開始時間:1571390681089
2019-10-18 17:24:41.138 INFO 6452 --- [nio-8080-exec-2] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2019-10-18 17:24:41.227 INFO 6452 --- [nio-8080-exec-2] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2019-10-18 17:24:41.255 INFO 6452 --- [nio-8080-exec-2] c.s.s.service.impl.UserService : 進入了UserService
2019-10-18 17:24:41.256 INFO 6452 --- [nio-8080-exec-2] c.s.s.service.util.RootService : 交易:userService結束時間:1571390681256
2019-10-18 17:24:41.256 INFO 6452 --- [nio-8080-exec-2] c.s.s.service.util.RootService : 交易:userService耗時:167

返回為:

{
 "user": {
 "user_id": "1","password": "123456","user_name": "張三"
 }
}

總結:這樣寫法的好處在於 1.有一個統一的入口,不需要在編寫controller,可以專注於業務(service)2.可以在公共入口做公共處理。

以上這篇在java中由類名和方法名字串實現其呼叫方式就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。