持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第32天,点击查看活动详情
四、依赖查找
- Spring依赖查找
ListableBeanFactory#getBeansOfType方法会导致bean提前初始化
类型安全的依赖查找:
-
ApplicationContenxt内建可查找的依赖
-
依赖查找中的常见异常
-
Spring getBean是否是线程安全的? 是的,加了synchronized锁
五、依赖注入
-
注入方式
-
字段注入:
- @Autowired
- 静态字段上使用不生效
@Autowired
private PersonHolder personHolder;
==限定bean名称注入==
@Autowired
@Qualifier("person")
private PersonHolder personHolder;
==分组注入==
@Autowire注解上加@Qualifier注解,可以将同样用@bean注解时加了@Qualifier的获取到。
==其他注入姿势==
@Autowired
private Map<String,User> users;
@Autowired
private List<User> userList;
@Autowired
private Optional<Person> userOptional;
@Autowired
private ObjectFactory<Person> userObjectFactory;
public class QualifierDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext();
applicationContext.register(QualifierDemo.class);
applicationContext.refresh();
System.out.println(applicationContext.getBean(QualifierDemo.class).users);
System.out.println(applicationContext.getBean(QualifierDemo.class).users2);
applicationContext.close();
}
@Autowired
private Collection<User> users;
@Autowired
@Qualifier
private Collection<User> users2;
@Bean
@Qualifier
public User user1(){
return createUser("user1");
}
@Bean
public User user2(){
return createUser("user2");
}
@Bean
public User user3(){
return createUser("user3");
}
private static User createUser(String name){
User user=new User();
user.setName(name);
return user;
}
}
- @Resource
- @Inject(类似于@Autowired)
- 方法注入
- @Autowired
private PersonHolder personHolder;
@Autowired
public void initPersonHolder(PersonHolder personHolder){
this.personHolder=personHolder;
}
- @Resource
- @Bean
@Bean
public PersonHolder personHolder(Person person){
return new PersonHolder(person);
}
- 接口回调注入
- Aware系列接口回调 例子:BeanFactoryAware
- @Autowire源码分析
- 元信息解析
- 依赖查找
- 依赖注入(字段、方法)
- 在AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition时就已经解析完元信息,形成了一个beanDefinition了。
- 通过buildAutowiringMetadata方法构建元信息
- 调用postProcessProperties方法,里面有inject方法,会遍历所有的elements(InjectedElement)执行inject方法
- 进入到AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject方法里面
- 调用DefaultListableBeanFactory#resolveDependency进行依赖查找
- 找到之后,通过反射将查找到的bean set到Field上去。
扩展点: InstantiationAwareBeanPostProcessor
另外@Bean使用中,如果你想让你的bean早点注入到话,可以在方法改为static方法
@Bean
public static User user(){
return createUser("user1");
}
六、依赖查找的来源
-
Spring内建BeanDefintion
-
Spring内建单例对象
-
Spring会默认创建4个对象:
- BeanFactory
- ResourceLoader
- ApplicationEventPublisher
- ApplicationContext
其中beanFactory是单独的,剩余3个注入的都是相同的对象
4. Spring依赖注入的来源
另外外部化的配置文件也能注入,如properties文件。
部分代码如下:
@PropertySource("default.properties")
public class QualifierDemo {
@Autowired
private BeanPostConfig beanPostConfig;
@Value("${user.age}")
private Integer age;
七、SpringBean作用域
spring作用域
- Singleton: Singleton Bean无论依赖查找还是依赖注入,均为同一个对象。Prototype Bean无论依赖查找还是依赖注入,均为新的对象。
- Prototype: 无论是Singleton还是Prototype都会执行初始化方法回调,但是Prototype不会执行销毁方法。
- Prototype的bean销毁方法可以通过实现DisposableBean接口来做
- requestScope:requestScope作用域,一个request一个线程去执行
- sessionScope:用户一个浏览器是公用一个session的,所以用户开多个tab共同操作是有线程安全问题的。
- applicationScope
- 自定义Scope
- 实现Scope接口
- 注册Scope
示例:RefreshScope类 7. singleton Bean是否在一个应用中是唯一的?
答:否,singleton Bean只在当前IOC容器中(BeanFactory)中是单例对象。
八、Spring Bean生命周期
- Spring Bean元信息资源配置
- xml和properties
- 代码示例:
DefaultListableBeanFactory beanFactory=new DefaultListableBeanFactory(); XmlBeanDefinitionReader beanDefinitionReader=new XmlBeanDefinitionReader(beanFactory); beanDefinitionReader.loadBeanDefinitions("dependency-lookup-context.xml"); System.out.println(Arrays.asList(beanFactory.getBeanDefinitionNames())); Person person = (Person)beanFactory.getBean("person"); System.out.println(person);
- Spring BeanDefinition的解析
DefaultListableBeanFactory beanFactory=new DefaultListableBeanFactory();
AnnotatedBeanDefinitionReader beanDefinitionReader=new AnnotatedBeanDefinitionReader(beanFactory);
beanDefinitionReader.register(BeanFactoryDemo.class);
BeanFactoryDemo bean = beanFactory.getBean(BeanFactoryDemo.class);
System.out.println(bean);
- Spring Bean合并阶段 org.springframework.beans.factory.support.AbstractBeanFactory#getMergedBeanDefinition(java.lang.String)
- Spring Bean实例化前阶段
@Configuration
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if(beanName.equals("user")){
System.out.println("use is replace");
User user=new User();
user.setName("new user");
return user;
}
//代表不操作,保持
return null;
}
}
- Spring Bean实例化后阶段
@Configuration
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println(beanName);
if(beanName.equals("user")){
User user = User.class.cast(bean);
user.setName("meini");
return false;
}
return true;
}
}
- Spring Bean属性赋值前阶段
1.2-5.0 版本:InstantiationAwareBeanPostProcessor#postProcessPropertyValues
5.1 版本之后:InstantiationAwareBeanPostProcessor#postProcessProperties
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if(beanName.equals("user")){
MutablePropertyValues propertyValues=new MutablePropertyValues();
propertyValues.addPropertyValue("name","tiantian");
return propertyValues;
}
return null;
}
}
-
Spring Aware接口
源码实现类:ApplicationContextAwareProcessor
-
Spring Bean初始化前阶段
@Configuration
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(beanName.equals("user")){
User user=(User)bean;
user.setName("v2");
return user;
}
return null;
}
}
- Spring Bean初始化阶段
执行顺序: @PostConstruct-》InitializingBean接口的afterPropertiesSet-》自定义的bean的init方法 - Spring Bean初始化后阶段
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(beanName.equals("user")){
User user=(User)bean;
user.setName("v2");
System.out.println("v5");
return user;
}
return null;
}
- Spring Bean初始化完成后的阶段
实现SmartInitializingSingleton#afterSingletonsInstantiated 12. Spring Bean销毁前阶段
@Configuration
public class MyDestructionAwareBeanPostProcessor implements DestructionAwareBeanPostProcessor {
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeDestruction");
}
}
- Spring Bean销毁阶段
- @PreDestory
- DisposableBean接口
- 自定义方法
- 面试题