• spring源码理解


    1. spring创建Bean

    如下配置:Spring是将接口UserMapper交给MapperFactoryBean, 实现里面的方法,产生一个代理对象,这样,代码中就可以使用@Autowired进行注入使用;

    1. //依赖xml, 单个mapper
    2. <bean id = "userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"
    3.     <property name="mappInterface" ref="org.mybatis.spring.sample.UserMapper" />
    4.     <property name="sqlSessionFactory" ref="sqlSessionFactory" />
    5. </bean>

     探究Spring是如何产生动态代理的?

    1. package com.feng.mapper;
    2. import com.feng.dto.UserDTO;
    3. import org.apache.ibatis.annotations.Insert;
    4. public interface UserMapper {
    5. @Insert("select * from tab_user")
    6. public void selectUser(UserDTO userDTO);
    7. }

    Spring 创建的动态代理类UserMapper是如何注入Spring容器中的?

    1. @Service
    2. public class UserService {
    3. /**
    4. * userMapper:Object
    5. * 动态代理
    6. */
    7. @Autowired
    8. private UserMapper userMapper;
    9. public void save(Map<String, Object> map){
    10. UserDTO userDTO = new UserDTO();
    11. userDTO.setId("111");
    12. userDTO.setUsername("zhangsan");
    13. userMapper.selectUser(userDTO);
    14. }
    15. }

    而我们自己代理产生的对象不在容器中,没办法注入

    1. Class[] clazz = new Class[]{ UserMapper.class };
    2. UserMapper userMapper = (UserMapper)Proxy.newProxyInstance(
    3. this.getClass().getClassLoader(),
    4. clazz,
    5. new UserMapperHandler());


    解决问题?
    如何把一个代理对象放入Spring容器中?

    Spring是如何放容器的?

    Spring实例化bean 读取类上的注解信息,比如@Compent

    spring先解析xml文件或者注解配置,读取所有要加载类信息。根据类信息创建对应的BeanDefinition对象,再根据Beandefination对象创建实例对象。

    一个普通类包含如下属性信息:

    • name
    • scope
    • 构造方法
    • 注入模型(byName or byType)
    • lazy
    • static

    将类上的信息放入BD中(BeanDefinition),如果有多个类就创建多个BD ,然后将DB放入BeanDefinitionMap中;

    BeanDefinition是SpringBean的描述对象,主要封装了如下信息:

    此时,如果程序员提供了一个类实现接口: BeanFactotyPostProcessor

    1. @FunctionalInterface
    2. public interface BeanFactoryPostProcessor {
    3.     void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
    4. }

    spring 将先处理实现类中的逻辑(可以拿到Map,进而修改了beanClass)
    然后Spring调用方法 preInstantiateSingletons, 根据BD中类的信息, 将bean给new出来;

    1. package org.springframework.beans.factory.config;
    2. import java.util.Iterator;
    3. import org.springframework.beans.BeansException;
    4. import org.springframework.beans.factory.ListableBeanFactory;
    5. import org.springframework.beans.factory.NoSuchBeanDefinitionException;
    6. import org.springframework.lang.Nullable;
    7. public interface ConfigurableListableBeanFactory extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {
    8. void registerResolvableDependency(Class<?> var1, @Nullable Object var2);
    9. boolean isAutowireCandidate(String var1, DependencyDescriptor var2) throws NoSuchBeanDefinitionException;
    10. BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
    11. Iterator<String> getBeanNamesIterator();
    12. //
    13. void preInstantiateSingletons() throws BeansException;
    14. }

            如果想要把代理对象放入容器中,就新生成一个BeanDefinition, 然后将BD放入Spring容器中,但是BeanFactotyPostProcessor 只提供了update方法,而没有提供add方法

            如何放入?

            Spring提供类一个接口:ImportBeanDefinitionRegistrar,可以注册BeanDefinition

    1. public interface ImportBeanDefinitionRegistrar {
    2.     default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
    3.      BeanDefinitionBuilder bdBuilder = BeanDefinition.genericBeanDefinition(UserFactoryBean.class);
    4.      AbstractBeanDefinition beanDefinition = bdBuilder.getBeanDefinition();
    5.     
    6.      beanDefinition.getConstructorArgumentValues()
    7. .addGenericArgumentValue("com.feng.mapper.UserMapper");
    8.     
    9.         registry.registerBeanDefinition("UserFactoryBean", beanDefinition);
    10.     }
    11.     default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    12.     }
    13. }


            FactoryBean 是一个bean,而且是一个特殊的bean,它实现了接口(依赖)

    @Import(ImportBeanDefinitionRegistrar.class)

    小结:Spring实例化一个Bean中,重要的三个接口:

    • BeanFactotyPostProcessor
    • ImportBeanDefinitionRegistrar
    • FactoryBean

    下面是普通类实例化的流程图:

  • 相关阅读:
    探索请求头中的UUID的不同版本:UUID1、UUID3、UUID4和UUID5
    dataloader重构与keras入门体验
    Shader中的渲染路径LightMode
    重装系统踩坑指南
    力扣labuladong一刷day13天双指针8道链表题
    基于go版本的LoraWAN Server 的470MHz频段的设置
    MindSponge分子动力学模拟——计算单点能(2023.08)
    AJAX——AJAX的异步与同步、AJAX代码封装
    CRMEB开源商城部署在腾讯云
    分销商城小程序开发运营逻辑是什么?
  • 原文地址:https://blog.csdn.net/tumu6889/article/details/125492610