千家信息网

怎么深度解析Spring5.0源码

发表于:2025-12-01 作者:千家信息网编辑
千家信息网最后更新 2025年12月01日,这篇文章将为大家详细讲解有关怎么深度解析Spring5.0源码,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。Spring核心注解原理这篇文章主要针对S
千家信息网最后更新 2025年12月01日怎么深度解析Spring5.0源码

这篇文章将为大家详细讲解有关怎么深度解析Spring5.0源码,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

Spring核心注解原理

这篇文章主要针对Spring核心注解进行分析

一:@Condition注解

Condition 是在spring4.0 增加的条件注解,通过这个可以功能可以实现选择性的注入Bean操作,接下来先学习下Condition是如何使用的,然后分析spring源码了解其中的实现原理。

实现案例:

在Spring容器加载中,如果当前环境是WIN7操作系统就装配win7实体类、其他系统就不装配。

@Configurationpublic class MyConfig {    /**     * Import作用主要将外部的jar包注入到springioc容器中 @Import(Win7Entity.class) 等于与@Bean     * Import注册的bean对象 id为当前类全路径     */    @Bean    public Win7Entity win7Entity() {        return new Win7Entity();    }
public class V1Spring {    public static void main(String[] args) {        // 1.基于注解方式实现启动        ApplicationContext annotationApplicationContext =                new AnnotationConfigApplicationContext(MyConfig.class);        Win7Entity win7Entity = (Win7Entity) annotationApplicationContext.getBean("win7Entity");        System.out.println(win7Entity);

输出结果

com.mayikt.v1.entity.Win7Entity@5606c0b

MyCondition

public class MyCondition implements Condition {    /**     * @param context  获取到当前的上下文     * @param metadata 获取当前注解的细心     * @return     */    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {        // 1.获取当前的环境        Environment environment = context.getEnvironment();        // win7 linux win8 win10 苹果系统MAC        String osName = environment.getProperty("os.name");        if (osName.equals("Windows 10")) {            // 可以注册该对象            return true;        }        // 不能注册该对象        return false;    }}
@Configurationpublic class MyConfig {    /**     * Import作用主要将外部的jar包注入到springioc容器中 @Import(Win7Entity.class) 等于与@Bean     * Import注册的bean对象 id为当前类全路径     */    @Bean    @Conditional(MyCondition.class)    public Win7Entity win7Entity() {        return new Win7Entity();    }

输出:

com.mayikt.v1.entity.Win7Entity@64d7f7e0

二:@Import注解

1.为什么要使用@Import注解?Import注解的主要作用的将外部的jar包注入到springioc容器中

2.@Bean注解应用场景是什么?注册加载外部jar包

@Configuration@Import(Win7Entity.class)public class MyConfig {    /**     * Import作用主要将外部的jar包注入到springioc容器中 @Import(Win7Entity.class) 等同于@Bean     * Import注册的bean对象 id为当前类全路径     */   /* @Bean    @Conditional(MyCondition.class)    public Win7Entity win7Entity() {        return new Win7Entity();    }*/
public class V1Spring {    public static void main(String[] args) {        // 1.基于注解方式实现启动        ApplicationContext annotationApplicationContext =                new AnnotationConfigApplicationContext(MyConfig.class);        Win7Entity win7Entity = (Win7Entity) annotationApplicationContext.getBean("com.mayikt.v1.entity.Win7Entity");//这里当前类Win7Entity的全路径        System.out.println(win7Entity);

结果:

com.mayikt.v1.entity.Win7Entity@f4168b8

public class V1Spring {    public static void main(String[] args) {        // 1.基于注解方式实现启动        ApplicationContext annotationApplicationContext =                new AnnotationConfigApplicationContext(MyConfig.class);        Win7Entity win7Entity = (Win7Entity) annotationApplicationContext.getBean("com.mayikt.v1.entity.Win7Entity");        System.out.println(win7Entity);        String[] beanDefinitionNames = annotationApplicationContext.getBeanDefinitionNames();        for (int i = 0; i < beanDefinitionNames.length; i++) {            System.out.println(beanDefinitionNames[i]);        }

结果

com.mayikt.v1.entity.Win7Entity@f4168b8org.springframework.context.annotation.internalConfigurationAnnotationProcessororg.springframework.context.annotation.internalAutowiredAnnotationProcessororg.springframework.context.annotation.internalRequiredAnnotationProcessororg.springframework.context.annotation.internalCommonAnnotationProcessororg.springframework.context.event.internalEventListenerProcessororg.springframework.context.event.internalEventListenerFactorymyConfigcom.mayikt.v1.entity.Win7Entity

总结下:@Bean注解与@Import注解的区别?

@Bean注解注册的bean的id是以方法名称来作为beanid ,

@Import注解以当前类的完整路径地址注册 ,相比来说@Import注入类更加简单

应用场景都是引入外部jar包

三@EnableXXX注解的实现原理

配合@Configuration使用,包括 @EnableAsync, @EnableScheduling, @EnableTransactionManagement, @EnableAspectJAutoProxy, @EnableWebMvc。

@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@Import({PayEntity.class,MyPayEntity.class}) //引入@Import注解public @interface EnablePayEntity {    // 只要启动的时候 加入该EnablePayEntity  就会将PayEntity实体类注入到spruingioc容器    // Enable注解的话 底层 实际上在调用@Import(PayEntity.class)}
@Configuration@Import(Win7Entity.class)@EnablePayEntity    //配置类加上这个注解public class MyConfig {    /**     * Import作用主要将外部的jar包注入到springioc容器中 @Import(Win7Entity.class) 等于与@Bean     * Import注册的bean对象 id为当前类全路径     */

程序输出结果

com.mayikt.v1.entity.Win7Entity@130f889org.springframework.context.annotation.internalConfigurationAnnotationProcessororg.springframework.context.annotation.internalAutowiredAnnotationProcessororg.springframework.context.annotation.internalRequiredAnnotationProcessororg.springframework.context.annotation.internalCommonAnnotationProcessororg.springframework.context.event.internalEventListenerProcessororg.springframework.context.event.internalEventListenerFactorymyConfigcom.mayikt.v1.entity.PayEntitycom.mayikt.v1.entity.MyPayEntitycom.mayikt.v1.entity.Win7Entity

@EnableXXX注解的实现原理:底层实际上还是调用@Import注解

四:ImportSelector类

public class MyImportSelector implements ImportSelector {    /**     *  注解信息     * @param importingClassMetadata     * @return     */    public String[] selectImports(AnnotationMetadata importingClassMetadata) {        //注入多个对象,类的完整路径        return new String[]{"com.mayikt.v1.entity.MemberEntity","com.mayikt.v1.entity.MsEntity"};    }}
@Configuration@Import({Win7Entity.class,MyImportSelector.class})@EnablePayEntitypublic class MyConfig {    /**     * Import作用主要将外部的jar包注入到springioc容器中 @Import(Win7Entity.class) 等于与@Bean     * Import注册的bean对象 id为当前类全路径     */

输出结果

com.mayikt.v1.entity.Win7Entity@16267862org.springframework.context.annotation.internalConfigurationAnnotationProcessororg.springframework.context.annotation.internalAutowiredAnnotationProcessororg.springframework.context.annotation.internalRequiredAnnotationProcessororg.springframework.context.annotation.internalCommonAnnotationProcessororg.springframework.context.event.internalEventListenerProcessororg.springframework.context.event.internalEventListenerFactorymyConfigcom.mayikt.v1.entity.PayEntitycom.mayikt.v1.entity.MyPayEntitycom.mayikt.v1.entity.Win7Entitycom.mayikt.v1.entity.MemberEntitycom.mayikt.v1.entity.MsEntity

五:ImportBeanDefinitionRegistrar

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {    /**     * AnnotationMetadata 注解的信息     * @param importingClassMetadata     * @param registry     */    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {        // spring容器中 bean 的信息 Bean Definition描述   手动注册到ioc容器中        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(SmsEntity.class);        registry.registerBeanDefinition("smsEntity", rootBeanDefinition);        // 底层源码:springioc 底层通过beanDefinitionMap存放 线程是安全的    }    //FactoryBean (往IOC容器存储对象 注入对象) BeanFactory(从ioc工厂获取bean对象)}

底层实现原理:

this.beanDefinitionMap.put(beanName, beanDefinition);
private final Map beanDefinitionMap = new ConcurrentHashMap(256)

底层通过一个ConcurrentHashMap保存起来的。

@Configuration@Import({Win7Entity.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})@EnablePayEntitypublic class MyConfig {    /**     * Import作用主要将外部的jar包注入到springioc容器中 @Import(Win7Entity.class) 等于与@Bean     * Import注册的bean对象 id为当前类全路径     */

输出结果

myConfigcom.mayikt.v1.entity.PayEntitycom.mayikt.v1.entity.MyPayEntitycom.mayikt.v1.entity.Win7Entitycom.mayikt.v1.entity.MemberEntitycom.mayikt.v1.entity.MsEntitysmsEntity

六:FactoryBean

public class MyFactoryBean implements FactoryBean {    public MyEntity getObject() throws Exception {        return new MyEntity();    }    public Class getObjectType() {        return MyEntity.class;    }    //往IOC容器中注入对象    public boolean isSingleton() {        // 默认的情况下就是为true true表示为单例 false 表示为多例        return false;    }}
@Configuration@Import({Win7Entity.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class,MyFactoryBean.class})@EnablePayEntitypublic class MyConfig {    /**     * Import作用主要将外部的jar包注入到springioc容器中 @Import(Win7Entity.class) 等于与@Bean     * Import注册的bean对象 id为当前类全路径     */

输出结果

myConfigcom.mayikt.v1.entity.PayEntitycom.mayikt.v1.entity.MyPayEntitycom.mayikt.v1.entity.Win7Entitycom.mayikt.v1.entity.MemberEntitycom.mayikt.v1.entity.MsEntitycom.mayikt.v2.config.MyFactoryBeansmsEntity

疑问:BeanFactory和FactoryBean区别?

BeanFactory是个Factory,也就是IOC容器或对象工厂,FactoryBean是个Bean。在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的。

但对FactoryBean而言,这个Bean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似

疑问:@Service与@Compent注解区别?

底层还是调用@Compont注解,主要是为了分类,更好划分场景,注意要加上扫包范围

@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpublic @interface Mayikt {}

Spring注释@Qualifie

在学习@Autowired的时候我们已经接触到了@Qualifier,这节就来详细学习一下自定义@Qualifier

例如定义一个交通工具类:Vehicle以及它的子类Bus和Sedan。

如果用@Autowired来找Vehicle的话,会有两个匹配的选项Bus和Sedan。为了限定选项,可以像下面这样。

@Autowired@Qualifier("car")private Vehicle vehicle;

如果要频繁使用@Qualifier("car")并且想让它变得更有意义,我们可以自定义一个@Qualifier。

@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Qualifierpublic @interface Car{}
 @Autowired  @Car  private Vehicle vehicle;

最后在Sedan类加上注释。

@Carpublic class Sedan implements Vehicle{}

疑问:@Primary与@Qualifier区别?

在一个接口下有两个实现类使用@Autowired获取的时候,有什么问题?

@Autowired默认情况下使用类型查找,会存在问题。SpringBoot多数据源 设置默认或者优先级。

解决方案:

@Resource按照名称查找;

@Qualifier指定实现类

@Primary指定实现类的优先级第一,默认获取

关于怎么深度解析Spring5.0源码就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

0