注解@component定义的bean怎么注入一个通过xml定义的bean
由于项目的需要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 TT getService(String classFullName) throws ClassNotFoundException,BeansException{
2 ClassT requiredType=(ClassT)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);
自主开发的、带有 @Component 的组件在Spring Boot 项目中不生效的解决方法
(1)问题描述
开发了一套组件,以 jar 形式发布。然后在 Spring Boot 项目中使用 pom引用后,无法调用到在组件中用 @Component 注释的类。
(2)原因分析
默认情况下,@ComponentScan注解会扫描当前包及其所有子包中的组件。而 @SpringBootApplication 注解包含了@ComponentScan,所以 Spring Boot 框架会自动扫描 Spring Boot启动类当前包及其所有子包中的组件类。而我们的组件因为不在自动扫描范围内,所以无效。
(3)问题解决
在 Spring Boot启动类中使用 @Import 注解,导入我们希望 Spring Boot 扫描的类。如果有多个类以逗号分隔。形如:
@Import(value = { ds.interceptor.SwitchDataSourceInterceptor.class,
ds.config.DatasourceMapperConfig.class,
ds.service.RSAServiceImpl.class
})
使用注解,spring中无法注入bean?
这种情况,帮你找到两种解决办法:
1 .将接口与对应的实现类放在与application启动类的同一个目录或者他的子目录下,这样注解可以被扫描到,这是最省事的办法
2 .在指定的application类上加上这么一行注解,手动指定application类要扫描哪些包下的注解
@Component注解的用法
遇到的问题
踩到一个坑,有一个接口,在这个接口的实现类里,需要用到@Autowired注解,一时大意,没有在实现类上加上@Component注解,导致了Spring报错,找不到这个类
一旦使用关于Spring的注解出现在类里,例如我在实现类中用到了@Autowired注解,被注解的这个类是从Spring容器中取出来的,那调用的实现类也需要被Spring容器管理,加上@Component
开发中难免会遇到这个这个注解@Component
@Controller 控制器(注入服务)
用于标注控制层,相当于struts中的action层
@Service 服务(注入dao)
用于标注服务层,主要用来进行业务的逻辑处理
@Repository(实现dao访问)
用于标注数据访问层,也可以说用于标注数据访问组件,即DAO组件
.
@Component (把普通pojo实例化到spring容器中,相当于配置文件中的 )
泛指各种组件,就是说当我们的类不属于各种归类的时候(不属于@Controller、@Services等的时候),我们就可以使用@Component来标注这个类。
没有component注解可以被注入吗
不是用的注解,那肯定就是在spring的配置文件applicationContext.xml里配置了bean。不一定说非得用注解才能注入的,用xml也能注入,道理是一样的。
你的第一个问题,在struts里写时应该是这样的,action name="abc" class="xxAction"/action
这里的class是spring配置文件里的某个bean的id, 这样struts才会交给spring去实例化action。
spring注解的service在springmvc的controller里面无法注入
虽然不知道那里出错了,但是看出个问题。
有了context:component-scan,另一个context:annotation-config/标签根本可以移除掉,因为已经被包含进去了。