以AnnotationConfigApplicationContext举例
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); UserService userService = (UserService) context.getBean("userService"); userService.test();
1:创建一个上下文对象
2:获取一个bean;
3:执行方法
AppConfig中的内容为:
@ComponentScan("com.zhouyu") public class AppConfig { @Bean public UserService userService(){ return new UserService(); } }
问题:为啥getbean("userService")可以拿到一个userService对象呢
需要关注的肯定就是new AnnotationConfigApplicationContext(Appconfig.class)和getbean里做了啥。也就是我们关注的spring帮我们做了啥。
在调用AnnotationConfigApplicationContext的构造函数时,spring确实帮我们做了以下工作,以下流程只是截取了一个分支的一小段逻辑,大致的一个流程
1:解析AppConfig配置类,得到扫描路径
2:遍历扫描路径下的所有的java类,如果发现某个类或者父注解上有@component注解,spring会将此类记录下来。存到一个Map
3:Spring会根据某个规则生成当前类对应的beanName,作为key存入Map,当前类作为value
4:beanDefinition中的name会注册到一个list中,遍历list,拿到Class对象,反射生成对象,放入单例池
然后调用context.getbean("userService"),从单例池中拿到对应的实例,执行test方法。
spring具体如果创建一个bean呢,大致如下
1:利用该类的构造函数来实例化得到一个对象,如类中存在多个构造函数,spring会进行选择,这个叫做推断构造方法,如下
(1):如果一个类中只有一个构造方法。无论是无参或者有参,spring都会采用这个构造方法
(2):如果多个构造方法,分情况
i:多个构造方法中存在一个无参构造方法,采用无参构造方法
ii:多个构造方法且无构造方法,spring会报错
iii:多个构造方法,有构造方法用Autowired修饰,spring采用此方法。
如果构造方法中存在参数的引用,spring会getbean入参
2:得到一个对象后,spring会对对象中@Autowired的属性进行依赖注入,依赖注入是在实例化后通过beanpostprocessor实现的
3:依赖注入以后,spring会判断该类是否实现了BeanNameAware接口,BeanClassLoaderAware接口、BeanFactoryAware接口,如果实现了,就表示当前对象必须实现该接口中所定义的setBeanName()、setBeanClassLoader()、setBeanFactory()方法,那Spring就会调用这些方法并传入相应的参数(Aware回调)
4:Aware回调后,Spring会判断对象中是否某个方法被@PostContruct注解修饰,如果存在,spring会调用次方法(初始化前)
5:Spring会判断对象是否实现了InitialzingBean接口,如果实现了,spring会调用该类中的afterPropertiesSet方法(初始化)
6:最后,Spring会判断当前对象需不需要进行AOP,如果不需要那么Bean就创建完了,如果需要进行AOP,则会进行动态代理并生成一个代理对象做为Bean(初始化后)
总结BeanPostProcessor- InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()实例化MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()自动注入InstantiationAwareBeanPostProcessor.postProcessProperties()Aware对象BeanPostProcessor.postProcessBeforeInitialization()初始化BeanPostProcessor.postProcessAfterInitialization()
大致的流程就是这样,写这些东西只是为了对自己学习的东西做一些总结,加深下映像,有可能有东西是表达错误或者很多东西没写到的,勿喷。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)