相关模块目录结构如下:
SpringBoot项目的启动类DemoApplication.java如下:
package com.cn.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ImportResource;
import com.cn.demo.common.utils.SpringContextUtil;
@SpringBootApplication
@ServletComponentScan
@ImportResource({"classpath*:/spring/*.xml"})
public class DemoApplication {
public static void main(String[] args) {
ApplicationContext applicationContext = SpringApplication.run(DemoApplication.class, args);
//设置应用程序上下文
SpringContextUtil.setApplicationContext(applicationContext);
}
}
获取上下文工具类SpringContextUtil.java如下:
package com.cn.demo.common.utils;
import org.springframework.context.ApplicationContext;
/**
* 获取上下文工具类
*/
public class SpringContextUtil {
private static ApplicationContext applicationContext;
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public static void setApplicationContext(ApplicationContext applicationContext) {
SpringContextUtil.applicationContext = applicationContext;
}
//返回指定bean的实例
public static Object getBean(String beanId) {
return applicationContext.getBean(beanId);
}
}
统一入口GateWayController.java如下:
package com.cn.demo.tests.beanname.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.fastjson.JSONObject;
import com.cn.demo.common.utils.SpringContextUtil;
import com.cn.demo.tests.beanname.service.BaseService;
@RestController
@RequestMapping("/unified")
public class GateWayController {
private static final Logger logger = LoggerFactory.getLogger(GateWayController.class);
@RequestMapping(value = "/api", method = RequestMethod.POST)
public JSONObject gatewayBusiness(@RequestBody JSONObject json) {
return dispatchService(json);
}
/**
* 服务转发器,避免反复引入服务类的实例
* @param json
* @return
*/
private JSONObject dispatchService(JSONObject json) {
String bizCode = json.getString("bizCode");
String serviceBeanName = getServiceBeanName(bizCode);
try {
BaseService service = (BaseService) SpringContextUtil.getBean(serviceBeanName);
JSONObject returnJson = service.service(json);
logger.info("返回值:" + returnJson);
return returnJson;
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 获取bean的名称:业务码+Service
* @param busiCode
* @return
*/
private String getServiceBeanName(String bizCode) {
return bizCode + "Service";
}
}
BaseService.java如下:
package com.cn.demo.tests.beanname.service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
/**
* 所有服务的基类
*/
public interface BaseService {
/**
* 每个服务必须实现这个接口
*
* @param json
* @return
*/
public JSONObject service(JSONObject json);
/**
* 初始化返回的JSON
* @return
*/
public default JSONObject getSuccessJson() {
JSONObject successJson = JSON.parseObject("{}");
successJson.put("returnCode", "0");
successJson.put("returnMsg", "SUCCESS");
return successJson;
}
}
MyTestService.java如下:
package com.cn.demo.tests.beanname.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONObject;
@Service
public class MyTestService implements BaseService {
private static final Logger logger = LoggerFactory.getLogger(MyTestService.class);
@Override
public JSONObject service(JSONObject json) {
logger.info("进入MyTestService服务...");
JSONObject returnJson = getSuccessJson();
return returnJson;
}
}
业务码bizCode为MyTest,进行调用
报错信息如下:org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'MyTestService' available
Spring配置元数据有以下三种方式:
-
基于 XML 的配置文件
-
基于注解的配置
- 基于 Java 的配置
此处使用的是基于注解@Service的配置。
通过分析AnnotationBeanNameGenerator.class得知,
org.springframework.beans.factory.support.BeanNameGenerator
用@Component
注解注释的bean类的实现,或者使用另一个本身用@Component
作为 meta-annotation的注解。例如, Spring的原型注解 (比如@Repository
) 本身就是用@Component
注释的。Also supports Java EE 6's
javax.annotation.ManagedBean
and JSR-330'sjavax.inject.Named
annotations, if available. Note that Spring component annotations always override such standard annotations.如果注解的值没有指明bean名称,则将基于类的短名称(首字母小写) 构建适当的名称。例如:
com.xyz.FooServiceImpl -> fooServiceImpl
由于我们在使用@Service注解的时候没有指示bean的名称,所以默认生成的bean名称为myTestService,找MyTestService时会找不到。
解决办法1:
将bizCode修改为myTestService,重新发送请求:
控制台打印如下:
解决办法2:
给MyTestService.java指示bean的名称,即给@Service注解添加value值为MyTestService,如下所示:
package com.cn.demo.tests.beanname.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONObject;
@Service(value = "MyTestService")
public class MyTestService implements BaseService {
private static final Logger logger = LoggerFactory.getLogger(MyTestService.class);
@Override
public JSONObject service(JSONObject json) {
logger.info("进入MyTestService服务...");
JSONObject returnJson = getSuccessJson();
return returnJson;
}
}
这时发送请求:
控制台打印如下:
扩展
上面函数的作用是:从给定的bean定义派生一个默认的bean名称。默认实现只是构建了一个短类名的去首字母大写版本。例如:"mypackage.MyJdbcDao" -> "myJdbcDao"。注意,内部类将因此具有"outerClassName.InnerClassName"形式的名称,这是因为名称中的句点可能是一个问题,如果你是自动命名。
上面函数的作用是:获取一个字符串并将其转换为普通Java变量名的大小写。这通常意味着将第一个字符从大写转换为小写,但在(不寻常的)特殊情况下,当有多个字符且第一个和第二个字符都是大写时,不管它。因此,"FooBah" 变成了 "fooBah" , "X" 变成了"x",但是"URL" 仍然是 "URL"。
新建一个类XService.java,如下:
package com.cn.demo.tests.beanname.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONObject;
@Service
public class XService implements BaseService{
private static final Logger logger = LoggerFactory.getLogger(XService.class);
@Override
public JSONObject service(JSONObject json) {
logger.info("进入XService服务...");
JSONObject returnJson = getSuccessJson();
return returnJson;
}
}
发送请求:
再新建一个类ABService.java,如下:
package com.cn.demo.tests.beanname.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONObject;
@Service
public class ABService implements BaseService{
private static final Logger logger = LoggerFactory.getLogger(ABService.class);
@Override
public JSONObject service(JSONObject json) {
logger.info("进入ABService服务...");
JSONObject returnJson = getSuccessJson();
return returnJson;
}
}
发送请求: