Spring由浅入深(下)

58 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第32天,点击查看活动详情

四、依赖查找

  1. Spring依赖查找

ListableBeanFactory#getBeansOfType方法会导致bean提前初始化

类型安全的依赖查找:

  1. ApplicationContenxt内建可查找的依赖

  2. 依赖查找中的常见异常

  3. Spring getBean是否是线程安全的? 是的,加了synchronized锁

五、依赖注入

  1. 注入方式

  2. 字段注入:

  • @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)
  1. 方法注入
  • @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);
    }
  1. 接口回调注入
  • Aware系列接口回调 例子:BeanFactoryAware
  1. @Autowire源码分析
  • 元信息解析
  • 依赖查找
  • 依赖注入(字段、方法)
  1. 在AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition时就已经解析完元信息,形成了一个beanDefinition了。
  2. 通过buildAutowiringMetadata方法构建元信息
  3. 调用postProcessProperties方法,里面有inject方法,会遍历所有的elements(InjectedElement)执行inject方法
  4. 进入到AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject方法里面
  5. 调用DefaultListableBeanFactory#resolveDependency进行依赖查找
  6. 找到之后,通过反射将查找到的bean set到Field上去。

扩展点: InstantiationAwareBeanPostProcessor

另外@Bean使用中,如果你想让你的bean早点注入到话,可以在方法改为static方法

    @Bean
    public  static User user(){
        return createUser("user1");
    }

六、依赖查找的来源

  1. Spring内建BeanDefintion

  2. Spring内建单例对象

  3. 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作用域

  1. Singleton: Singleton Bean无论依赖查找还是依赖注入,均为同一个对象。Prototype Bean无论依赖查找还是依赖注入,均为新的对象。
  2. Prototype: 无论是Singleton还是Prototype都会执行初始化方法回调,但是Prototype不会执行销毁方法。
  • Prototype的bean销毁方法可以通过实现DisposableBean接口来做
  1. requestScope:requestScope作用域,一个request一个线程去执行
  2. sessionScope:用户一个浏览器是公用一个session的,所以用户开多个tab共同操作是有线程安全问题的。
  3. applicationScope
  4. 自定义Scope
  • 实现Scope接口
  • 注册Scope

示例:RefreshScope类 7. singleton Bean是否在一个应用中是唯一的?

答:否,singleton Bean只在当前IOC容器中(BeanFactory)中是单例对象。

八、Spring Bean生命周期

  1. 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);
    
  1. 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);

  1. Spring Bean合并阶段 org.springframework.beans.factory.support.AbstractBeanFactory#getMergedBeanDefinition(java.lang.String)
  2. 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;
    }
}
  1. 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;
    }
}
  1. 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;
    }

}
  1. Spring Aware接口 源码实现类:ApplicationContextAwareProcessor

  2. 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;
    }
    
}
  1. Spring Bean初始化阶段
    执行顺序: @PostConstruct-》InitializingBean接口的afterPropertiesSet-》自定义的bean的init方法
  2. 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;
    }
  1. 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");
    }
}

  1. Spring Bean销毁阶段
  • @PreDestory
  • DisposableBean接口
  • 自定义方法
  1. 面试题