复习spring框架的时候遇到的一个小问题,作为对spring认识的补充记录下来。
假设这样一种环境:
在一个简单的SSM项目中,我们在spring对service层的配置文件applicationContext-service.xml中配置了包扫描范围——仅扫描service包
<context:component-scan base-package="com.guli.service" />
这时我们在com.guli.service2包下新建一个TestService类,定义如下:
package com.guli.service2;
import org.springframework.beans.factory.annotation.Autowired;
import com.guli.mapper.UserMapper;
import com.guli.pojo.User;
public class TestService {
@Autowired
UserMapper userMapper;
public User getUserById(Integer id) {
return userMapper.getUserById(id);
}
}
当然,因为是现成 的项目所以我在这里直接注入了mybatis的映射接口UserMapper,换成其他类也行,这和本文要说明的点关系不大。
然后在applicationContext-service.xml配置文件中声明一个bean:
<bean id="testService" class="com.guli.service2.TestService" />
最后写一个测试方法:
@Test
public void testSpring() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"classpath:spring/applicationContext-*.xml");
TestService testService = applicationContext.getBean(TestService.class);
User user = testService.getUserById(1);
System.out.println(user);
}
环境准备完毕,请注意:
1. TestService不在spring的包扫描范围内,但是含有@Autowired注解;
2. TestService本身是通过spring的xml注册的,而非注解;
3. 在xml中注册TestService的bean的时候,没有注入UserMapper的依赖;
那么问题来了:测试类中的testService对象依赖的UserMapper可以被注入吗?
答案是:可以。
原因:
首先,在spring配置文件中<context:component-scan>包含了<context:annotation-config/>,如果配置了前者,后者就不许要配置了。
下面我们重点关注<context:annotation-config/>标签:
<context:annotation-config/>的作用是向Spring容器注册以下四个BeanPostProcessor:
- AutowiredAnnotationBeanPostProcessor
- CommonAnnotationBeanPostProcessor
- PersistenceAnnotationBeanPostProcessor
- RequiredAnnotationBeanPostProcessor
以上四个Processor能够让系统识别@Autowired、@Required等注解,并激活所有在spring容器中注册过的bean中包含的这些注解,无论这些bean是通过包扫描的方式注册的还是在通过xml的方式注册的。
因此,在我们上面测试环境中,即使TestService不在包扫描范围内,只要TestService在xml中注册了,@Autowired就可以生效。