概述
依赖查找的来源:除容器内建和自定义Spring Bean之外,还有其他来源提供依赖查找吗?
依赖注入的来源:难道依赖注入的来源与依赖查找的不同吗?
public class DependencySourceDemo {
// 注入在 postProcessProperties 方法执行,早于 setter注入,也早于 @PostConstruct
@Autowired
private BeanFactory beanFactory;
@Autowired
private ResourceLoader resourceLoader;
@Autowired
private ApplicationContext applicationContext;
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
@PostConstruct
public void initByInjection() {
System.out.println("beanFactory == applicationContext " + (beanFactory == applicationContext));
System.out.println("beanFactory == applicationContext.getBeanFactory() " + (beanFactory == applicationContext.getAutowireCapableBeanFactory()));
System.out.println("resourceLoader == applicationContext " + (resourceLoader == applicationContext));
System.out.println("ApplicationEventPublisher == applicationContext " + (applicationEventPublisher == applicationContext));
}
@PostConstruct
public void initByLookup() {
getBean(BeanFactory.class);
getBean(ApplicationContext.class);
getBean(ResourceLoader.class);
getBean(ApplicationEventPublisher.class);
}
private <T> T getBean(Class<T> beanType) {
try {
return beanFactory.getBean(beanType);
} catch (NoSuchBeanDefinitionException e) {
System.err.println("当前类型" + beanType.getName() + " 无法在 BeanFactory 中查找!");
}
return null;
}
public static void main(String[] args) {
// 创建 BeanFactory 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册 Configuration Class(配置类) -> Spring Bean
applicationContext.register(DependencySourceDemo.class);
// 启动 Spring 应用上下文
applicationContext.refresh();
// 依赖查找 DependencySourceDemo Bean
DependencySourceDemo demo = applicationContext.getBean(DependencySourceDemo.class);
// 显示地关闭 Spring 应用上下文
applicationContext.close();
}
}
依赖查找的来源 依赖注入都支持, 而且依赖注入比依赖查找多非spring容器管理对象.
Spring IOC的三种依赖来源,自定义注册的Spring bean、内建的Spring bean以及内建的可注入的依赖,其中自定义注册的Spring bean基本上是通过xml、注解或者api注册BeanDefination创建的,内建的Spring bean是通过registerSingleton()创建的,内建的可注入的依赖是通过registerResolveDependency()创建的,后续如果我们需要往Spring容器里放入一些非Spring托管的bean但又可以被依赖注入的, 可以通过registerResolveDependency() API实现
Spring容器管理和游离对象:为什么会有管理对象和游离对象?
单体对象就是已初始化的外部 Java 对象,在 Spring 容器中是唯一的
单体对象是最普通的 Spring IoC 中使用的对象,而游离对象主要是类似 scope 为 prototype 这样的获取对象。
Spring Bean Definition作为依赖来源:Spring Bean的来源
单例对象作为依赖来源:单体对象与普通Spring Bean存在哪些差异?
为什么说单例对象无法实现延迟初始化bean,不是有lazy么?
因为单体对象是外部已初始化对象,所以不存在 Lazy 的问题,Lazy 针对于 BeanDefinition,而非具体对象。
非Spring容器管理对象作为依赖来源:如何理解ResolvableDependency?
public class ResolvableDependencySourceDemo {
@Autowired
private String value;
@PostConstruct
public void init() {
System.out.println(value);
}
public static void main(String[] args) {
// 创建 BeanFactory 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册 Configuration Class(配置类) -> Spring Bean
applicationContext.register(ResolvableDependencySourceDemo.class);
applicationContext.addBeanFactoryPostProcessor(beanFactory -> {
// 注册 Resolvable Dependency
beanFactory.registerResolvableDependency(String.class, "Hello,World");
});
// 启动 Spring 应用上下文
applicationContext.refresh();
// 显示地关闭 Spring 应用上下文
applicationContext.close();
}
}
总结:注册非spring管理的依赖对象时,可以通过两种方式实现
1.通过ApplicationContext.getBeanFactory()获取AnnotationConfigApplicationContext创建时初始化的DefaultListableBeanFactory对象,然后调用registryResolveableDependency来注册,为啥不能通过getAutowireCapableBeanFactory()来获取beanFactory对象,因为方法中需要beanFactory已被激活即执行了ApplicationContext的refresh()操作之后
2.通过addBeanFactoryPostProcessor回调方式实现,因为当refresh()方法执行invokeBeanFactoryPostProcessors()时会遍历已创建的beanFactoryPostProcessors集合对象来执行postProcessBeanFactory()方法
annotationConfigApplicationContext.getAutowireCapableBeanFactory();这种方式,会调用assertBeanFactoryActive(),验证BeanFactory;使用annotationConfigApplicationContext.getBeanFactory();就不会报错,
因为没有验证环节 所以这样也是可以的
ConfigurableListableBeanFactory beanFactory = annotationConfigApplicationContext.getBeanFactory();
beanFactory.registerResolvableDependency(String.class,"hello world");
annotationConfigApplicationContext.register(ResolvableDependencySourceDemo.class);
annotationConfigApplicationContext.refresh();
外部化配置作为依赖来源:@Value是如何将外部化配置注入Spring Bean的?
@Configuration
@PropertySource(value = "META-INF/default.properties",encoding="UTF-8")
public class ExternalConfigurationDependencySourceDemo {
@Value("${user.id:-1}")
private Long id;
@Value("${usr.name}")
private String name;
@Value("${user.resource:classpath://default.properties}")
private Resource resource;
public static void main(String[] args) {
// 创建 BeanFactory 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册 Configuration Class(配置类) -> Spring Bean
applicationContext.register(ExternalConfigurationDependencySourceDemo.class);
// 启动 Spring 应用上下文
applicationContext.refresh();
// 依赖查找 ExternalConfigurationDependencySourceDemo Bean
ExternalConfigurationDependencySourceDemo demo = applicationContext.getBean(ExternalConfigurationDependencySourceDemo.class);
System.out.println("demo.id = " + demo.id);
System.out.println("demo.name = " + demo.name);
System.out.println("demo.resource = " + demo.resource);
// 显示地关闭 Spring 应用上下文
applicationContext.close();
}
}
通过@Value属性读取通过@PropertySource所关联的文件,若有字符集设置可通过@PropertySource中encoding设置
面试题
不过 Spring IoC 最大特性是 DI,所以启动 ApplicationContext 后,再注册并查找 Bean 价值不大了~
最后
以上就是沉静猫咪为你收集整理的第七章:Spring IoC依赖来源(Dependency Sources)的全部内容,希望文章能够帮你解决第七章:Spring IoC依赖来源(Dependency Sources)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复