Spring继续学习: IOC、Bean、拓展点.....

IOC加载

IOC加载过程就是bean的创建过程

在这里插入图片描述

  • 通过@Bean <bean/> @Component 去定义一个bean (概念态)
  • 实例化ApplicationContext对象,读取Bean的定义信息@Bean <bean/> @Component
  • 创建Bean工厂
  • 调用bean工厂的后置处理器,可自定义修改bean定义,注册成BeanDefinition(定义态)

invokeBeanFactoryPostProcessors(beanFactory)

  • 判断beanDefiniton是否符合生产标准(是不是抽象的,单例,懒加载)
  • 通过反射实例化对象(纯净态)(循环依赖
  • 生命周期钩子函数
  • 创建完成,put到单例池子 ConcurrentHashMap<String,Object>

Bean生命周期

  • Bean的实例化阶段

  • Bean的设置属性阶段

    • 循环依赖
    • 在设置属性阶段后,postProcessBeforeInitialization方法执行前,会执行很多Aware类型的接口,这种类型接口作用是加载资源到Spring容器中,Aware前面的名字就对应哪种资源,依次加载的是:
      BeanNameAware
      BeanClassLoaderAware
      BeanFactoryAware
      EnvironmentAware
      ResourceLoaderAware
      ApplicationEventPublisherAware
      ApplicationContextAware
  • Bean的 初始化阶段

    • InitializingBean的afterPropertiesSet方法
    • @PostConstruct注解标注的方法
    • 配置的init-method
    • 上面的三个方法效果都是一样的
  • Bean的销毁阶段

    • preDestroy注解标注的方法
    • DisposableBean接口的destroy方法
    • 配置的destroy-method

初始化阶段,有个特别重要的接口BeanPostProcessor,在初始化前、后调用。

Demo

借用一个博主的demo
在这里插入图片描述
测试类

public class BeanLifeTest {
    @Test
    public void test(){
        System.out.println("Spring容器初始化===========================");
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        System.out.println("Spring容器初始化完毕========================");
        System.out.println("从容器中获取Bean");
        IocBeanLifeService service = context.getBean("iocBeanLifeService", IocBeanLifeService.class);
        System.out.println(service.toString());
        System.out.println("Spring容器准备关闭==========================");
        context.close();
        System.out.println("Spring容器完成关闭===========================");
    }
}

所有Bean在初始化前后都会执行

public class CustomerBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("【步骤10】执行BeanPostProcessor中postProcessBeforeInitialization方法,beanName=" + beanName);
        return bean;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("【步骤14】执行BeanPostProcessor的postProcessAfterInitialization方法,beanName=" + beanName);
        return bean;
    }
}

Demo Bean

public class IocBeanLifeService implements InitializingBean,DisposableBean,ApplicationContextAware,
        ApplicationEventPublisherAware, BeanClassLoaderAware, BeanFactoryAware,
        BeanNameAware, EnvironmentAware, ImportAware, ResourceLoaderAware{
    private String name;
    private String sex;
    public void setName(String name) {
        System.out.println("【步骤2】执行Bean的set方法,设置name属性值:" + name);
        this.name = name;
    }
    public void setSex(String sex) {
        System.out.println("【步骤2】执行Bean的set方法,设置sex属性值:" + sex);
        this.sex = sex;
    }
    public IocBeanLifeService(){
        System.out.println("【步骤1】执行Bean的无参构造函数");
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("【步骤12】执行InitializingBean的afterPropertiesSet方法");
    }
    @Override
    public void destroy() throws Exception {
        System.out.println("【步骤16】执行DisposableBean接口的destroy方法");
    }
    //通过<bean>的destroy-method属性指定的销毁方法
    public void destroyMethod() throws Exception {
        System.out.println("【步骤17】执行配置的destroy-method");
    }
    //通过<bean>的init-method属性指定的初始化方法
    public void initMethod() throws Exception {
        System.out.println("【步骤13】执行配置的init-method");
    }
    @PostConstruct
    public void initPostConstruct(){
        System.out.println("【步骤11】执行PostConstruct注解标注的方法");
    }
    @PreDestroy
    public void preDestroy(){
        System.out.println("【步骤15】执行preDestroy注解标注的方法");
    }
    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("【步骤4】执行BeanClassLoaderAware中setBeanClassLoader,ClassLoader的name = " + classLoader.getClass().getName());
    }
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("【步骤5】执行BeanFactoryAware中setBeanFactory,beanFactory中是否包含IocBeanLifeService:" + beanFactory.containsBean("iocBeanLifeService"));
    }
    @Override
    public void setBeanName(String s) {
        System.out.println("【步骤3】执行BeanNameAware中setBeanName方法,beanName值:"
                + s);
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("【步骤9】执行ApplicationContextAware的setApplicationContext方法,Bean Definition Names="
                + Arrays.toString(applicationContext.getBeanDefinitionNames()));
    }
    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        System.out.println("【步骤8】执行ApplicationEventPublisherAware中setApplicationEventPublisher方法");
    }
    @Override
    public void setEnvironment(Environment environment) {
        System.out.println("【步骤6】执行EnvironmentAware的setEnvironment方法");
    }
    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        Resource resource = resourceLoader.getResource("classpath:applicationContext.xml");
        System.out.println("【步骤7】执行ResourceLoaderAware的setResourceLoader方法,Resource File Name="
                + resource.getFilename());
    }
    @Override
    public void setImportMetadata(AnnotationMetadata annotationMetadata) {
        System.out.println("执行setImportMetadata");
    }
}

Spring拓展点

XxxAware

上面的demo有

Bean初始化前后:BeanPostProcessor

场景:所有Bean在初始化前后,都会执行上面说到的BeanPostProcessor 的Before和After方法。

所有BeanDefinition注册后:BeanFactoryPostProcessor

如下,将已经注册的Definition设置为懒加载。

@Component
public class A implements BeanFactoryPostProcessor {

    //在所有BeanDefinition注册完之后调用。
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException {
        //所有BeanDefinition名
        for (String beanDefinitionName : factory.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }
        //设置懒加载
        BeanDefinition beanDefinition = factory.getBeanDefinition("userService");
        beanDefinition.setLazyInit(true);
    }
}

@PostConstruct失效

主页文章:@PostConstruct 失效之(Bean实现了BeanFactoryPostProcessor)

所有Bean就绪后:ApplicationListener、CommandLineRunner

场景:在所有Bean就绪之后,执行。
是通过监听接口方式启动
两种方式

1.
@Component
public class B implements ApplicationListener<ContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        System.out.println("所有Bean已经准备就绪");
    }
}
或者
@Component
public class B{
	   @EventListener(ContextRefreshedEvent.class)
	   public void onContextRefreshed(ContextRefreshedEvent contextRefreshedEvent){
	       System.out.println("BBB");
	   }
}
2.
@Component
public class StartPingService implements CommandLineRunner{
	@Override
	public void run(String... args) throws Exception {
		System.out.println("所有Bean已经准备就绪");
	}
}

@Import

@Import的几种用法
在这里插入图片描述
在这里插入图片描述

找到多个Bean时不报错

Bean不唯一的时候,如有两个不同的Bean继承同一接口,都在容器中。
这时候获取bean报错,说bean不唯一

解决:
添加@Primary注解,将它设为主Bean

@Autowared和@Resources

一个是Spring提供,一个是JDK提供

前者先按照类型匹配,再按照名称
后者先按照名称匹配,再按照类型

@Autowared自动装配过程

在这里插入图片描述

@Configuration

加了@Configuration会为配置类创建cglib动态代理(保证配置类@Bean方法只执行一次来实现单例)

Spring注册Mybatis的Mapper为Bean

Mapper都是接口且没有实现类,怎么注册为Bean?

SpringMVC处理json

在这里插入图片描述

SSM中的父子容器

在这里插入图片描述

SpringBoot

是个啥
在这里插入图片描述
Spring和SpringBoot
Spring是一个框架,而SpringBoot是快速构建基于Spring的脚手架,为开发Spring及其它框架铺平了道路

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值