SpringBoot中使用bean名称转发服务:NoSuchBeanDefinitionException: No bean named ‘MyTestService‘ available

 相关模块目录结构如下:

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's javax.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;
	}

}

 发送请求:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值