Spring原理源码

一.容器接口

1.1.BeanFactory功能

1.什么是BeanFactory

  • 他是ApplicationContent 的父接口
  • 它才是Spring的核心容器,主要的ApplicationContext实现都【组合】了它的功能

2.类图:在这里插入图片描述3.BeanFactory功能

  • 表面上只有getBean
  • 实际上控制反转,基本的依赖注入,直至Bean的生命周期的各种功能,都由它的实现类提供

1.2.ApplicationContext的扩展功能

1.类图:
在这里插入图片描述2.拓展的功能

  1. 国际化
ConfigurableApplicationContext context = SpringApplication.run(DoucaiWebApplication.class, args);
        System.out.println(context.getMessage("hi",null, Locale.CHINA));
        System.out.println(context.getMessage("hi",null, Locale.ENGLISH));
        System.out.println(context.getMessage("hi",null, Locale.JAPANESE));

运行结果:
在这里插入图片描述

  1. 获取资源
ConfigurableApplicationContext context = SpringApplication.run(DoucaiWebApplication.class, args);
Resource[] resource = content.getResources("classpath*:META/spring.factories");
        for (Resource resource1 : resource) {
            System.out.println(resource);
        }

运行结果:
在这里插入图片描述

  1. 获取环境信息
ConfigurableApplicationContext context = SpringApplication.run(DoucaiWebApplication.class, args);
        System.out.println(context.getEnvironment().getProperty("java_home"));

运行结果:
在这里插入图片描述

  1. 发送事件
			 /**
         * 1.需要创建事件对象
         * 2.创建监听器对象 :监听到了就执行任务
         */
        context.publishEvent(new UserRegisteredEvent(context));

在这里插入图片描述

二.容器实现

2.1.BeanFactory实现的特点

public class TestBeanFactory {
    /**
     * 
     * a.beanFactory不会做的事
     *      1.不会主动调用BeanFactory 后处理器
     *      2.不会主动添加 Bean 后处理器
     *      3.不会主动初始化单例
     *      4.不会解析beanFactory 还不会解析 ${}与#{}
     * b.bean 后处理器会有排序的逻辑
     */

    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // bean 的定义(class,scope,初始化,销毁)

        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();

        //把beanDefinition放入beanFactory中
        beanFactory.registerBeanDefinition("config",beanDefinition);

        for (String name : beanFactory.getBeanDefinitionNames()) {
            System.out.println(name);
        }

        System.out.println("============================================================");
        //给BeanFactory添加后处理器 用于解析 一些注解
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
        // beanFactory后处理器主要功能,补充一些bean的定义
        beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().stream().forEach(beanFactoryPostProcessor -> {
            beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
        });

        // Bean后处理器,针对bean的生命周期的各个阶段提供扩展,例如@Autowired @Resource
        beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor);
        // 就可以获取到Bean1中的Bean2了
        System.out.println(beanFactory.getBean(Bean1.class).getBean2());

        // 预先将Bean工厂中的单利对象先创建出来
        beanFactory.preInstantiateSingletons();



    }


    @Configuration
    static class Config {
        @Bean
        public Bean1 bean1() {
            return new Bean1();
        }

        @Bean
        public Bean2 bean2() {
            return new Bean2();
        }
    }


    static class Bean1 {
        private static final Logger log = LoggerFactory.getLogger(Bean1.class);

        public Bean1() {
            System.out.println("构造Bean1");
        }

        @Autowired
        private Bean2 bean2;

        public Bean2 getBean2() {
            return bean2;
        }
    }


    static class Bean2 {
        private static final Logger log = LoggerFactory.getLogger(Bean2.class);

        public Bean2() {
            System.out.println("构造Bean2");
        }
    }
}

2.2.ApplicationContext的常见实现实现和用法

   //1.较为经典的容器 基于classpath下xml格式的配置文件来创建
    private static void testClassPathXmlApplicationContext() {
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("b01.xml");
        for (String name : context.getBeanDefinitionNames()) {
            System.out.println(name);
        }
        System.out.println(context.getBean(Bean2.class).getBean1());
    }

    //2.基于磁盘路径下xml格式的配置文件来创建
    private static void testFileSystemXmlApplicationContext() {
        FileSystemXmlApplicationContext context =
                new FileSystemXmlApplicationContext("src\\main\\resources\\b01.xml");
        for (String name : context.getBeanDefinitionNames()) {
            System.out.println(name);
        }
        System.out.println(context.getBean(Bean2.class).getBean1());
    }
    
    //3.较为经典的容器,基于java 配置类来创建
    private static void testAnnotationConfigApplicationContext() {
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(Config.class);
        for (String name : context.getBeanDefinitionNames()) {
            System.out.println(name);
            System.out.println(context.getBean(Bean2.class).getBean1());
        }
		@Configuration
            static class Config {
                @Bean
                public Bean1 bean1() {
                    return new Bean1();
                }

                @Bean
                public Bean2 bean2(Bean1 bean1) {
                    Bean2 bean2 = new Bean2();
                    bean2.setBean1(bean1);
                    return  bean2;
                }
                    return new Bean2();
                }
            }



   //4.较为经典的容器,基于java 配置类来创建,用于 web 环境
    private static void testAnnotationConfigServletWebServerApplicationContext() {
        AnnotationConfigServletWebServerApplicationContext context =
                new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);

    }
        @Configuration
    static class WebConfig{
        @Bean
        public  static ServletWebServerFactory serverFactory(){
            return new TomcatServletWebServerFactory();
        }

        @Bean
        public  static DispatcherServlet dispatcherServlet(){
            return new DispatcherServlet();
        }

        @Bean
        public DispatcherServletRegistrationBean registrationBean(DispatcherServlet dispatcherServlet){
            return new DispatcherServletRegistrationBean(dispatcherServlet,"/");
        }

        @Bean("/hello")
        public Controller controller1( ){
            return (request, response) -> {
                response.getWriter().print("hello");
                return null;
            };
        }
    }

问:ApplicationContext是如何读取到xml中的bean信息的呢?
答:通过XmlBeanDefinitionReader(代码如下)

  DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    System.out.println("读取之前...");
    for (String name : beanFactory.getBeanDefinitionNames()) {
        System.out.println(name);
    }
    System.out.println("读取之后...");
    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
    reader.LoadBeanDefinitions(new ClassPathResource("b01.xml"));
    for (String name : beanFactory.getBeanDefinitionNames()) {
        System.out.println(name);

    }

运行结果:
在这里插入图片描述

三.Bean的生命周期

3.1 Spring bean 生命周期各个阶段

在这里插入图片描述

3.2模版方法设计模式

通过模版方法设计模式,可以在不改变getBean()方法的前提下拓展getBean()的功能
如下代码只是一个简单示例:给代码增加@Autowired和@Resource等操作

 public class Demo01 {
    public static void main(String[] args) {
        MyBeanFactory myBeanFactory = new MyBeanFactory();
        myBeanFactory.addBeanPostProcesser(bean -> {System.out.println("@Autowired操作");});
        myBeanFactory.addBeanPostProcesser(bean -> {System.out.println("@Resource操作");});
        myBeanFactory.getBean();


    }


    static class MyBeanFactory{
        private List<BeanPostProcesser> list = new ArrayList<>();
        public Object getBean(){
            Object bean = new Object();
            System.out.println("构造"+bean);
            System.out.println("依赖注入"+bean);
            for (BeanPostProcesser beanPostProcesser : list) {
                beanPostProcesser.inject(bean);
            }
            System.out.println("初始化"+bean);
            return bean;
        }


        public void addBeanPostProcesser(BeanPostProcesser beanPostProcesser){
            list.add(beanPostProcesser);
        }
    }

    static interface BeanPostProcesser{
         void inject(Object bean);
    }
}

四.Bean后处理器

4.1Bean后处理器作用

为Bean生命周期各个阶段提供扩展

4.2常见的后处理器

一:常见后处理器

  • AutowiredAnnotationBeanPostProcessor 可以处理@Autwired @Value 这些注解进行增强
  • CommonAnnotationBeanPostProcessor 可以处理@Resource @PostConstruct @PreDestroy 这些注解进行增强
  • ConfigurationPropertiesBindingPostProcessor.register(context.getDefaultListableBeanFactory()) 可以处理@ConfigurationProperties 这些注解进行增强

二:@Autowired Bean后处理器
DigInautowired.class

public class DigInautowired {
    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.registerSingleton("bean2",new Bean2());
        beanFactory.registerSingleton("bean1",new Bean1());
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());

        
        // 1.查找哪些属性,方法加了@Autowired,这称之为InjectionMetadata
        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
        processor.setBeanFactory(beanFactory);

        Bean1 bean1 = new Bean1();
        System.out.println(bean1);
        // 该方法就是执行依赖注入 @Autowired @Value
        processor.postProcessProperties(null,bean1,"bean1");
        System.out.println(bean1);

    }

Bean1.class

public class Bean1 {
    private Bean2 bean2;

    private static final Logger log = LoggerFactory.getLogger(Bean1.class);

    @Autowired
    public void setBean2(Bean2  bean2){
        log.debug("@Autowired 生效1:{}",bean2);
        this.bean2 = bean2;
    }
    @Autowired
    public void setHome(@Value("${JAVA_HOME}") String home){
        log.debug("@Autowired 生效2: {}",home);
    }
}

Bean2.class

public class Bean2 {

}

如下截图中的findAutowiringMetadata方法就是寻找对象中的有@Autowired标注的方法和属性,可以从截图中看见
它注入了 bean1中锁包含的对象
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值