栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

spring源码理解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

spring源码理解

1. spring创建Bean

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

//依赖xml, 单个mapper

    

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

package com.feng.mapper;

import com.feng.dto.UserDTO;
import org.apache.ibatis.annotations.Insert;

public interface UserMapper {

    @Insert("select * from tab_user")
    public void selectUser(UserDTO userDTO);

}

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

@Service
public class UserService {

    
    @Autowired
    private UserMapper userMapper;

    public void save(Map map){
        
        UserDTO userDTO = new UserDTO();
        userDTO.setId("111");
        userDTO.setUsername("zhangsan");

        userMapper.selectUser(userDTO);
    }

}

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

Class[] clazz = new Class[]{ UserMapper.class };
UserMapper userMapper = (UserMapper)Proxy.newProxyInstance(
                                        this.getClass().getClassLoader(), 
                                        clazz, 
                                        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

@FunctionalInterface
public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

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

package org.springframework.beans.factory.config;

import java.util.Iterator;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.lang.Nullable;

public interface ConfigurableListableBeanFactory extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {

    void registerResolvableDependency(Class var1, @Nullable Object var2);

    boolean isAutowireCandidate(String var1, DependencyDescriptor var2) throws NoSuchBeanDefinitionException;

    BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;

    Iterator getBeanNamesIterator();

    //
    void preInstantiateSingletons() throws BeansException;
}

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

        如何放入?

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

public interface ImportBeanDefinitionRegistrar {

    default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {

        BeanDefinitionBuilder bdBuilder =  BeanDefinition.genericBeanDefinition(UserFactoryBean.class);
        AbstractBeanDefinition beanDefinition = bdBuilder.getBeanDefinition();
    
        beanDefinition.getConstructorArgumentValues()
                      .addGenericArgumentValue("com.feng.mapper.UserMapper");
    
        registry.registerBeanDefinition("UserFactoryBean", beanDefinition);
    }

    default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    }
}


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

@Import(ImportBeanDefinitionRegistrar.class)

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

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/996360.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号