首先 @Import value 里的值通常是带有@configuration或者实现ImportBeanDefinitionRegistrar,ImportSelector接口 这几种。
如果是普通的业务类呢会怎么样?比如只是添加@Component 或者@Service 之类的呢?甚至这个类就没有交给spring 管理的呢?
package com.spring.demo.service.impl;
import com.spring.demo.service.TestService;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
/**
* @author haoran
*/
@Service
public class TestServiceImpl implements TestService , InitializingBean {
public void init(){
System.out.println("this is postConstruct method");
}
public TestServiceImpl(){
System.out.println("调用 TestService ------");
}
public void helloSpring(){
System.out.println("hello Spring");
}
@Override
public void sendMessage(String message) {
System.out.println("hello! "+message);
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("this is InitializingBean");
}
}
/**
* @author haoran
*/
@Configuration(proxyBeanMethods = false)
@ComponentScan(value = "com.spring")
//@RemoteScan(url = "com.spring.demo.api")
@Import(TestServiceImpl.class)
public class Config {
}
/**
* @author haoran
*/
public class TestMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Config.class);
TestService testService = annotationConfigApplicationContext.getBean(TestService.class);
testService.sendMessage("1111");
}
}
输出结果
> Task :spring-demo:TestMain.main()
调用 TestService ------
this is InitializingBean
hello! 1111
BUILD SUCCESSFUL in 5s
由此看来 import value 里是业务类也是没有问题的
如果我去掉@Service 注解呢,会怎么样呢
/**
* @author haoran
*/
//@Service
public class TestServiceImpl implements TestService , InitializingBean {
public void init(){
System.out.println("this is postConstruct method");
}
public TestServiceImpl(){
System.out.println("调用 TestService ------");
}
public void helloSpring(){
System.out.println("hello Spring");
}
@Override
public void sendMessage(String message) {
System.out.println("hello! "+message);
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("this is InitializingBean");
}
}
> Task :spring-demo:TestMain.main()
调用 TestService ------
this is InitializingBean
hello! 1111
执行结果是没有问题的
那由此可以盲猜 @import 注解有@Compontent 作用,也就是说可以将value 里的类交给spring 管理。
那我就尝试下跟中源码看下,@Import 到底是在何时将该类交给spring 管理的
processConfigBeanDefinitions prase.png
processConfigurationClass.png
asSourceClass.png
doprocessConfigurationClass.png image.png processImports.png
最后一行红字是错误的这里并没有将TestServiceImpl 注册到Spring里
processConfigurationClass.png image.png
image.png
image.png
image.png
image.png
@Import注解value 类的注入算是执行完成了,虽然TestServiceImpl 类被作为了带有@configuration 注解的类但是它并不完全等于带有@Configuration 的类,这个类是没有被增强的 一般带有@Configuration 注解的类 是会被spring 增强为代理类 即被cglib 代理。关于这些可以看下往期相关的文章。
至此可以的出结论 @Import 可以将一个不被spring 管理的类 变为spring 管理的类,即将value 里所引用的类注册到spring。
总结:开始spring 在解析config 类的时候 查到有个引用类@import(value= TestServiceImpl.class) 并将TestServiceImpl 作为ConfigClass(即带有@Configuration 的类) 放入到一个list 里 当config 解析完成后会调用一个loadBeanDefinitions(configClasses) 方法 加载扫描的配置类集合 将这些类转换为BeanDefinition 紧接着调用registerBeanDefinition() 方法注册到beanDefinitionMap 里至此TestServiceImpl.class 的注册到beanDefinitionMap里的步骤就结束了 后续就是普通的Bean 的流程。
网友评论