由于项目的需要spring的业务相关的bean不是写在xml文件中,因为项目是一个模块一个模块提交的,提交的时候不想修改xml文件,因此就用到了spring的注解Service。

例如:

Java代码

1 @Service("TestService")
2 public class TestService {
3 }

这等同于:

1 <bean id="TestService" class="TestService"/>  

spring会在classpath里面扫描标记有TestService等标签的类,扫描组件的配置如下:

Xml代码

1 <!-- sdp-service主要是注入服务类 -->
2
3 <context:component-scanbase-package="org.sdp"/>

加上以上的配置后,spring会自动的扫描org.sdp文件下的标记有注释的类。

以上的配置看似很“完美”,其实如果项目稍微大时就会出现问题,大家都知道spring的bean的id必须唯一,如果两个人同事写代码就有可以造成写同样的bean名称。

解决这个问题的一个思路是把bean的名称修改为 类的全路径,例如org.sdp.A 和com.bey.A 。

只要修改spring默认的bean命名策略就可以了。

AnnotationBeanNameGenerator是bean的默认命名策略,他实现了BeanNameGenerator接口。在Service里面,如果不写bean的名称,那么默认的名曾是类名,但是第一个字母是小写的。

例如:

Html代码

1 com.xyz.FooServiceImpl -> fooServiceImpl  

观察spring的源代码发现,buildDefaultBeanName方法首先了bean名称小写的作用。

1 protected String buildDefaultBeanName(BeanDefinition definition) {
2 String shortClassName = ClassUtils.getShortName(definition.getBeanClassName());
3 return Introspector.decapitalize(shortClassName);
4
5 }

因此,可以写一个类继承自AnnotationBeanNameGenerator,重写buildDefaultBeanName方法。

Java代码

1 public class SdpAnnotationBeanNameGenerator extends AnnotationBeanNameGenerator {
2 @Override
3 protected String buildDefaultBeanName(BeanDefinitiondefinition) {
4 return definition.getBeanClassName();
5 }
6 }

我的改写代码:

 1 @Override
2 protected String buildDefaultBeanName(BeanDefinition definition) {
3 String className =definition.getBeanClassName();
4
5 className=className.substring(className.lastIndexOf(".")+1);
6 if(className.toLowerCase().endsWith("impl")){
7 className=className.substring(0, className.length()-4);
8 }
9 if((className.toLowerCase().endsWith("service")||className.toLowerCase().endsWith("dao"))==false){
10 return super.buildDefaultBeanName(definition);
11 }
12
13
14 className=className.substring(0,1).toLowerCase() + className.substring(1);
15 return className;
16 }

在扫描配置中需要添加自己的命名策略类:

1 <!-- sdp-service主要是注入服务类 -->
2 <context:component-scan base-package="org.sdp" name-generator="org.sdp.spring.SdpAnnotationBeanNameGenerator" />

通过以上配置,业务相关的bean不用写bean的名称了,ApplicationContext.getBean("类的全路径")就可以得到类的实例了。

如果是spring2.5则就结束了,但是spring3.0为完美提供了getBean(name,requiredType);使用了泛型,因此只要传入一个业务类的Class,getBean就返回此类的实例,而不用在

强制转换类型了。

1 public static <T>T getService(String classFullName) throws ClassNotFoundException,BeansException{
2 Class<T> requiredType=(Class<T>)Class.forName(classFullName);
3 return SdpContext.getContext().getBean(classFullName,requiredType); }

强制转换类型代码:

Java代码

1 TestService testService2=(TestService ) SdpContext.getContext().getBean("TestService ");
2 System.out.println(testService2);

改进后的代码:

Java代码

1 @Service
2 public class TestService { }
1 TestService testService=SdpContext.getService("org.sdp.context.TestService");
2 System.out.println(testService);

自定义Spring注解bean的命名策略的更多相关文章

  1. (转)Spring中Bean的命名问题(id和name区别)及ref和idref之间的区别

    Spring中Bean的命名 1.每个Bean可以有一个id属性,并可以根据该id在IoC容器中查找该Bean,该id属性值必须在IoC容器中唯一: 2.可以不指定id属性,只指定全限定类名,如: & ...

  2. Spring中Bean的命名问题(id和name区别)及ref和idref之间的区别

    Spring中Bean的命名 1.每个Bean可以有一个id属性,并可以根据该id在IoC容器中查找该Bean,该id属性值必须在IoC容器中唯一: 2.可以不指定id属性,只指定全限定类名,如: & ...

  3. Spring中Bean的命名问题及ref和idref之间的区别

    一直在用Spring,其实对其了解甚少,刚去了解了一下Spring中Bean的命名问题以及ref和idref之间的区别,略作记录,以备后查. Spring中Bean的命名 1.每个Bean可以有一个i ...

  4. spring注解-bean生命周期

    https://www.jianshu.com/p/70b935f2b3fe bean的生命周期 bean创建---初始化----销毁的过程 容器管理bean的生命周期 对象创建:容器启动后调用bea ...

  5. Spring 注解bean默认名称规则

    在使用@Component.@Repository.@Service.@Controller等注解创建bean时,如果不指定bean名称,bean名称的默认规则是类名的首字母小写,如SysConfig ...

  6. Spring bean自定义命名策略(注解实现)

    我们都知道项目后台开发是从 控制层——业务层——mybatis层,@Controller.@Service.@Mapper...等等注解可以将对象自动加载到bean容器中,还能实现相应的功能,使用起来 ...

  7. spring 注解方式配置Bean

    Spring能够从classpath下自动扫描,侦测和实例化具有特定注解的组件特定组件包括: @Component:基本注解,标示了一个受Spring管理的Bean组件 @Respository:标识 ...

  8. 5.spring:注解配置 Bean

    在classpath中扫描组件 组键扫描:能够从classpath下自动扫描,侦测和实例化具有特定注解的组件 特定的组件包括: ->@Componment:基于注解,标识一个受Spring管理的 ...

  9. Spring中Bean命名源码分析

    Spring中Bean命名源码分析 一.案例代码 首先是demo的整体结构 其次是各个部分的代码,代码本身比较简单,不是我们关注的重点 配置类 /** * @Author Helius * @Crea ...

随机推荐

  1. 哈希小demo hashCode取模

    package demo; import java.util.ArrayList; import java.util.List; class Person { private String usern ...

  2. Unite 2017 | 从《闹闹天宫》看MOBA游戏里的网络同步技术

    http://mp.weixin.qq.com/s/0v0EU79Q6rFafrh8ptlmhw 在Unite 2017 Shanghai案例分享专场,来自蓝港互动<闹闹天宫>项目组的主程 ...

  3. java容器的总结

    1.什么是容器? 在程序中,容器是一种用来容纳对象的数据结构,比如说list.set .map.queue. 2.为什么需要容器? 我们为什么需要容器呢?因为在程序中,我们会在任意时刻和任意位置创建任 ...

  4. UITableView加载网络数据的优化

    UITableView加载网络数据的优化 效果 源码 https://github.com/YouXianMing/Animations // // TableViewLoadDataControll ...

  5. 详细解读Volley(二)—— ImageRequest & Request简介

    上篇文章我们讲到了如何用volley进行简单的网络请求,我们可以很容易的接受到string.JsonObjec类型的返回结果,之前的例子仅仅是一次请求,这里需要说明volley本身就是适合高并发的,所 ...

  6. 低版本系统兼容的ActionBar(一)设置颜色+添加Menu+添加ActionMode

        之前我一直用ActionBarSherlock这个开源项目来做ActionBar,因为它可以让低版本的设备也能用上ActionBar.但是在最新的SDK中Google提供了一个AppCompa ...

  7. 安卓调试桥(ADB)环境变量的配置

    第一步,打开环境变量配置窗口.右击计算机,属性-高级系统设置-环境变量. 第二步,添加android系统环境变量.在系统变量下点击新建按钮,输入环境变量名ADB(自己随便写)           变量 ...

  8. [转]hive metadata 存mysql 注释中文乱码的有关

    FROM : http://blog.csdn.net/tswisdom/article/details/41444287 hive metadata 存mysql 注释中文乱码的问题 hive me ...

  9. 【转】搜狗开源内部项目管理平台Cynthia意欲何为

    FROM : http://blog.csdn.net/dj0379/article/details/38356825 目前,在项目管理与缺陷管理系统上,中国的中小开发团队基本都在使用国外产品,在理念 ...

  10. 程序中try、throw、catch三者之间的关系

    c++程序中,采用一种专门的结构化处理逻辑的异常处理机制. 1.try语句 try语句块的作用是启动异常处理机制,检测try语句块中程序语句执行时可能出现的异常. try语句块总是与catch一同出现 ...