@Import 注解调用流程一

2022-05-21  本文已影响0人  simians

首先 @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 的流程。

上一篇下一篇

猜你喜欢

热点阅读