SpringBoot八种bean的加载方式一学就会

news2025/7/9 11:34:57

目录

文章目录

    • @[toc]
    • 第一种bean的加载方式-配置文件
    • 第二种加载bean方式-注解和扫描
      • 创建第三方的bean对象
    • 第三种加载bean方式-不使用配置文件
      • 扩展-bean的加载方式扩展FactoryBean<>
      • 扩展-@ImportResource导入配置文件
      • 扩展-proxyBeanMethods属性-产生代理对象
    • 第四种加载bean方式-使用@Import
    • 第五种加载bean方式-registerBean
    • 第六种加载bean方式-实现ImportSelector接口
    • 第七种加载bean方式-实现ImportBeanDefinitionRegistrar
    • 第八种bean的加载方式-实现BeanDefinitionRegistryPostProcessor
    • 实现bean的方式总结

第一种bean的加载方式-配置文件

先创建一个使用maven的spring工程

导入spring核心配置

        <dependency>



            <groupId>org.springframework</groupId>



            <artifactId>spring-context</artifactId>



            <version>5.3.9</version>



        </dependency>

创建一个类

public  class Cat {



    



}
public class Dog {



}

创建一个名为applicationContext.xml的配置文件

<?xml version="1.0" encoding="UTF-8"?>



<beans xmlns="http://www.springframework.org/schema/beans"



       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"



       xsi:schemaLocation=



         "http://www.springframework.org/schema/beans



        http://www.springframework.org/schema/beans/spring-beans.xsd">



 



    <bean id="cat" class="com.service.Cat"/>



<bean id="dog" class="com.service.Dog"/>



 



</beans>

创建一个启动类

package com.app;



 



import com.service.Dog;



import org.springframework.context.ApplicationContext;



import org.springframework.context.support.ClassPathXmlApplicationContext;



 



public class App1 {



    public static void main(String[] args) {



        ApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml");



        Object cat = app.getBean("cat");//根据id获取



        System.out.println(cat);



        Object dog = app.getBean(Dog.class);//根据类获取,当不唯一时会报错



        System.out.println(dog);



 



    }



}

运行结果,这样就可以得到bean的对象了

img

或者使用可以使用一次性获取所有bean

public class App1 {



    public static void main(String[] args) {



        ApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml");



 



        String[] names = app.getBeanDefinitionNames();



        for (String name : names) {



            System.out.println(name);



        }



    }



}

运行结果

img

第二种加载bean方式-注解和扫描

使用注解,注解的作用就是替代配置文件的配置,注解有@Component @Service @Repository等

替换配置文件中的<bean id= class=…>

@Component("cat") //起的名



public class Cat {



 



}
@Component



public class Dog {



}

使用完注解还得让spring去扫描到这个注解,在配置文件中的写

<?xml version="1.0" encoding="UTF-8"?>



<beans xmlns="http://www.springframework.org/schema/beans"



       xmlns:context="http://www.springframework.org/schema/context"



       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"



       xsi:schemaLocation=



         "http://www.springframework.org/schema/beans



        http://www.springframework.org/schema/beans/spring-beans.xsd







          http://www.springframework.org/schema/context



        http://www.springframework.org/schema/context/spring-context.xsd







">



 



<!--告诉spring扫描哪个包component导入context命名空间-->



    <context:component-scan base-package="com"/>



    



 



</beans>

运行结果

img

创建第三方的bean对象

先导入对应的坐标

               <dependency>



                    <groupId>com.alibaba</groupId>



                    <artifactId>druid</artifactId>



                    <version>1.1.24</version>



                </dependency>

创建一个类,返回你需要导入的对象即可,加入注解

package com.config;



 



import com.alibaba.druid.pool.DruidDataSource;



import org.springframework.context.annotation.Bean;



import org.springframework.stereotype.Component;



 



@Component



public class DBconfig {



    @Bean



    public DruidDataSource dataSource(){



        DruidDataSource ds =new DruidDataSource();



        return ds;



    }



}

运行结果

img

第三种加载bean方式-不使用配置文件

创建一个类代替配置文件

package com.config;



 



import org.springframework.context.annotation.ComponentScan;



import org.springframework.context.annotation.Configuration;



 



@Configuration//定义为配置类



@ComponentScan({"com.config","com.service"}) //注解扫描包



public class springConfig {



}

运行类也得修改

package com.app;



 



import com.config.springConfig;



import org.springframework.context.ApplicationContext;



import org.springframework.context.annotation.AnnotationConfigApplicationContext;



import org.springframework.context.support.ClassPathXmlApplicationContext;



 



public class App2 {



    public static void main(String[] args) {



ApplicationContext app=new AnnotationConfigApplicationContext(springConfig.class);



 



        String[] names = app.getBeanDefinitionNames();



        for (String name : names) {



            System.out.println(name);



        }



    }



}

运行结果

img

扩展-bean的加载方式扩展FactoryBean<>

初始化实现FactoryBean<>接口的类,实现对bean加载到容器之前的批处理操作。

实现了FactoryBean接口创建出来的对象不是本身而是里面的泛型。

创建一个类实现接口

package com.config;




import com.service.Dog;

import org.springframework.beans.factory.FactoryBean;

import org.springframework.context.annotation.Bean;

public class DogFactoryBean implements FactoryBean<Dog> {

    public Dog getObject() throws Exception 

        return new Dog();

    }

//返回对象的类型

    public Class<?> getObjectType() {
        //这里可以做一系列的初始化工作
        return Dog.class;

    }

    //是否是单例,单例则多次获取都是一个对象
    public boolean isSingleton() {

        return false;

    }

}
@Component
public class Dog {

}

启动的主类

import com.config.springConfig;

import org.springframework.context.ApplicationContext;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App2 {
    public static void main(String[] args) {
ApplicationContext app=new AnnotationConfigApplicationContext(springConfig.class);
        String[] names = app.getBeanDefinitionNames();
        for (String name : names) {

            System.out.println(name);

        }
        System.out.println(app.getBean("dog1"));
        System.out.println(app.getBean("dog1"));
    }
}

运行结果

img

产生的是泛型的对象

扩展-@ImportResource导入配置文件

img

看源码可知道,可以写入多个string类型的数组,使用{}

@ImportResource({"applicationContext2.xml","applicationContext.xml"})
@Configuration
@ComponentScan("com")
@ImportResource({"applicationContext2.xml","applicationContext.xml"})
public class SpringConfig2 {
    @Bean
    public Cat cat(){
        return new Cat();
    }
}

两个配置文件中的bean,排在前面的首先加载,后面的之后加载,同的内容以之后的为主,不同的内容都加载。

扩展-proxyBeanMethods属性-产生代理对象

@Configuration注解中有一属性proxyBeanMethod属性,默认值是true

img

值为false时

@Configuration(proxyBeanMethods = false)
@ComponentScan("com")
@ImportResource({"applicationContext2.xml","applicationContext.xml"})
public class SpringConfig2 {

    @Bean

    public Cat cat(){
        return new Cat();
    }

}

主方法中

public class app3 {

    public static void main(String[] args) {

        ApplicationContext app=new AnnotationConfigApplicationContext(SpringConfig2.class);

        String[] names = app.getBeanDefinitionNames();

        for (String name : names) {

            System.out.println(name);

        }
        System.out.println("--------");

        System.out.println(app.getBean("springConfig2"))

        SpringConfig2 springConfig2 = app.getBean("springConfig2", SpringConfig2.class);
        System.out.println(springConfig2.cat());
        System.out.println(springConfig2.cat());
        System.out.println(springConfig2.cat());
    }
}

运行结果

img

产生的是普通对象,每一次调用方法都会new一个新的对象前提是这个方法是被bean管理的对象。

值为true时

不写或写true时

@Configuration(proxyBeanMethods = true)
@ComponentScan("com")
@ImportResource({"applicationContext2.xml","applicationContext.xml"})
public class SpringConfig2 {

    @Bean
    public Cat cat(){
        return new Cat();
    }
}

运行结果

img

会产生一个代理对象,这个代理对象让我们每次调用方法是都是同一个,前提也是需要被bean容器管理

注:产生的bean对象没指定名称时,默认是方法名或类名首字母小写,如类名是SpringTest则产生的bean是springTest

第四种加载bean方式-使用@Import

翻看@Import源码可知,需要一个类class字节码对象

img

在类中

import com.service.TestBean1;

import com.service.TestBean2;

import org.springframework.context.annotation.Import;


@Import({TestBean1.class, TestBean2.class})
public class springConfig4 {

}

创建测试的类

public class TestBean1 {
}
public class testBean2 {
}

主类上

public class app4 {

    public static void main(String[] args) {

        ApplicationContext app=new AnnotationConfigApplicationContext(springConfig4.class);
        String[] names = app.getBeanDefinitionNames();
        for (String name : names) {

            System.out.println(name);

        }
    }

}

运行结果

img

全路径名,加入的类即使没有被spring管理也可以产生bean。

第五种加载bean方式-registerBean

使用上下文对象在容器初始化后注入bean

在创建完上下文对象的时候可以加载bean

只能使用 AnnotationConfigApplicationContext获取上下文对象

public class app5 {

    public static void main(String[] args) {

        AnnotationConfigApplicationContext app=new AnnotationConfigApplicationContext(springConfig5.class);
    //加载完成后

        app.registerBean("CaiDog", Dog.class,1 );

        app.registerBean("CaiDog", Dog.class,2);

        app.registerBean("CaiDog", Dog.class,3 );

        String[] names = app.getBeanDefinitionNames();

        for (String name : names) {

            System.out.println(name);
        }

        System.out.println("------");
        System.out.println(app.getBean(Dog.class));
    }

}

Dog类下

@Component
public class Dog {

    int age;

    public Dog(){}

    public Dog(int age){

        this.age=age;

    }

    @Override
    public String toString() {

        return "Dog{" +

                "age=" + age +

                '}';
    }

}

运行结果 ,当有多个的时候,且bean的名字一致时,以最后的为准。

img

或者直接使用

app.register(Cat.class);

也可以快速的加载一个bean

img

第六种加载bean方式-实现ImportSelector接口

这个接口有许多方法用来判定

img

导入实现了ImportSelector接口的类,实现对导入源的编程式处理

public class MyImportSelector implements ImportSelector {

    public String[] selectImports(AnnotationMetadata annotationMetadata) {//AnnotationMetadata 注解的源数据

     //  做判定条件,是否有这个注解

        boolean flag = annotationMetadata.hasAnnotation("org.springframework.context.annotation.Configuration");

        if (flag){

            return new String[]{"com.service.Dog"};

        }

        return new String[]{"com.service.Cat"};
    }

}
@Import({MyImportSelector.class})

public class SpringConfig6 {

}
public class app6 {

    public static void main(String[] args) {

        ApplicationContext app=new AnnotationConfigApplicationContext(SpringConfig6.class);

        String[] names = app.getBeanDefinitionNames();

        for (String name : names) {

            System.out.println(name);


        }

    }

}

运行结果

img

第七种加载bean方式-实现ImportBeanDefinitionRegistrar

导入实现ImportBeanDefinitionRegistrar接口的类,通过BeanDefinition的注册器注册实名bean,实现对容器中bean的决定,例如对现有的bean的覆盖,进而达到

import com.service.Dog;

import org.springframework.beans.factory.config.BeanDefinition;

import org.springframework.beans.factory.support.BeanDefinitionBuilder;

import org.springframework.beans.factory.support.BeanDefinitionRegistry;

import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;

import org.springframework.core.type.AnnotationMetadata;

public class MyRegistrar implements ImportBeanDefinitionRegistrar {

    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        BeanDefinition beanDefinition= BeanDefinitionBuilder.rootBeanDefinition(Dog.class).getBeanDefinition();

        registry.registerBeanDefinition("woDog", beanDefinition);

    }

}
@Import({MyRegistrar.class})

public class SpringConfig7 {

}

运行结果

img

第八种bean的加载方式-实现BeanDefinitionRegistryPostProcessor

导入实现了BeanDefinitionRegistryPostProcessor接口的类,通过BeanDefintion的注册器注册实名bean,实现对容器中bean的最终裁定.(以这个接口加载的bean为主)

@Component

public class DBconfig {

    @Bean

    public DruidDataSource dataSource(){

        DruidDataSource ds =new DruidDataSource();

        return ds;

    }

}
public class MyPostProcessor implements BeanDefinitionRegistryPostProcessor {


    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {


 BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(DBconfig.class).getBeanDefinition();


    registry.registerBeanDefinition("dataSource",beanDefinition);

    }


    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }


}
@Import({MyPostProcessor.class})

public class SpringConfig8 {

}

运行结果

img

实现bean的方式总结

1.xml+

2.xml:context+注解(@Component+4个@Bean

3.配置类+扫描+注解(@Component+4个@Bean)

  • @Bean定义FactoryBean接口
  • @ImportResource
  • @Configuration注解的proxyBeanMethods属性

4.@Import导入bean的类

  • @Import导入配置类

5.AnnotationConfigApplicationContext调用register方法

6.@Import导入ImportSelector接口

7.@Import导入ImportBeanDefinitionRegistrar接口

8.@Import导入BeanDefinitionRegistryPostProcessor接口

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/9125.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一文读懂,python实现常用的数据编码和对称加密

相信很多使用 python 的小伙伴在工作中都遇到过&#xff0c;对数据进行相关编码或加密的需求&#xff0c;今天这篇文章主要给大家介绍对于一些常用的数据编码和数据加密的方式&#xff0c;如何使用 python 去实现。话不多说&#xff0c;接下来直接进入主题&#xff1a; 1、bas…

Windows OpenGL ES 图像灰度图

目录 一.OpenGL ES 图像灰度图 1.原始图片2.效果演示 二.OpenGL ES 图像灰度图源码下载三.猜你喜欢 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 基础 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 特效 零基础 Open…

Redis添加至windows服务

1.进入redis文件夹 打开redis所在文件夹&#xff0c;在资源管理器地址栏输入cmd&#xff0c;打开管理员命令提示符窗口。 2.配置服务参数 打开redis.windows.conf文件&#xff0c;找到“requirepass”配置项&#xff0c;此处设置redis密码&#xff0c;如果不需要密码&#xff0…

Python如何使用HanNLP工具

Python如何使用HanNLP工具目录系统安装配置 JDK 1.8系统安装 Visual C 2015下载 HanNLP 包测试HanNLP工具目录 目标&#xff1a;使用pycharm调用HanNLP工具完成对文本的分词、自动摘要、关键词提取等任务。 系统安装配置 JDK 1.8 1、windows环境下载 JDK 1.8 2、安装 JDK 1.…

Oracle PrimaveraUnifier空间管理器(Space Manager)

目录 前言 介绍 前言 在Oracle Primavera Unifier设施和资产管理基础产品中除了业务流程及配置管理器之外&#xff0c;其预配置设计还包含本文要介绍的空间管理器&#xff0c;即Space Manager 在Unifier中&#xff0c;空间管理器是用户可以执行设施管理任务的地方。空间管…

xv6---Lab1: Xv6 and Unix utilities

目录 参考资料&#xff1a; 1.1进程和内存 1.2 I/O 和文件描述符 1.3管道 源码&#xff1a; 调试环境搭建 sleep PingPong primes find xargs 参考资料&#xff1a; Lab: Xv6 and Unix utilities xv6-book翻译(自用&#xff09;第一章 - 知乎 1.1进程和内存 一个xv…

html中css的基础学习

小李胖了吗 I 都说秋天适合思念&#xff0c;其实更适合见面【小李胖了吗 I 都说秋天适合思念&#xff0c;其实更适合见面】 https://www.bilibili.com/video/BV19g411B7uL/?share_sourcecopy_web&vd_source385ba0043075be7c24c4aeb4aaa73352 通过本博文的学习&#xff0c…

常见的软件测试面试题,千万别答错了

软件测试的童鞋们&#xff0c;在面试测试工作时&#xff0c;一定遇到面试官问过这个问题&#xff1a; 软件测试的目的意义是什么&#xff1f;大家是怎么回答的呢&#xff1f;如果这个问题回答好了&#xff0c;说明你对软件测试工作的价值与意义了如指掌。 有经验的测试人员可…

[数据结构]栈和队列面试题解析

作者&#xff1a; 华丞臧. 专栏&#xff1a;【数据结构】 各位读者老爷如果觉得博主写的不错&#xff0c;请诸位多多支持(点赞收藏关注)。如果有错误的地方&#xff0c;欢迎在评论区指出。 推荐一款刷题网站 &#x1f449; LeetCode刷题网站 文章目录一、有效括号题目描述解题思…

freemarker+yml介绍 以及freemarker与JSP的区别

目录 1. freemarker介绍 2. freemarker使用步骤 2.1 在pom.xml引入freeMarker的依赖包 2.2 在springboot中添加freemarker配置 2.3 编写模板文件*.ftl(当做jsp使用即可) ​编辑 2.4 访问控制器后进行页面跳转 3. freemarker常用语法 3.1 取值 3.2 条件 3.3 循环 3…

超赞:不愧是“阿里内部Redis学习笔记”从头到尾,全是精华

近几年&#xff0c;随着移动互联网的飞速发展&#xff0c;我们享受着整个社会的技术进步带来的便利&#xff0c;但同时也给从业者带来了如何保证项目的高并发、低延时的技术挑战&#xff0c;相应的互联网技术也随之发生了重大变革&#xff0c;NoSQL技术得到了蓬勃的发展。 Red…

【JavaSE】抽象类与接口

文章目录抽象类的概念抽象类的语法抽象类的特性接口的概念接口的语法接口的特性多接口的实现接口的继承抽象类的概念 什么是抽象类呢&#xff1f;我们先来看一个例子&#xff1a;一个父类是动物类&#xff0c;两个子类一个狗狗类&#xff0c;一个猫猫类。 Animal中有一个dark…

有趣的statement stack

引子 在使用events_statements_current的过程中发现&#xff0c;同一线程在同一时刻&#xff0c;可能有多条记录&#xff0c;与直观感觉不太一样&#xff0c;于是跟踪了一下内部实现&#xff0c;有了本文。 STATEMENT STACK的定义 STATEMENT STACK 是events_statements_curr…

Linux基础内容(11)—— 进程理解

目录 1.进程状态 1.只针对操作系统的宏观概念 2.Linux的进程状态 1.运行状态(R) 2.休眠状态(S) 3.暂停状态/浅度睡眠状态(T) 4.深度睡眠状态(D) 5.当前进程正在被追踪(t) 6.死亡状态(X) 7.僵尸状态(Z) 8.孤儿进程 2.进程的优先级 1.优先级定义 2.Linux的优先级表现…

matlab 小数据法求liyapunov指数

1、内容简介 略 625-可以交流、咨询、答疑 2、内容说明 摘 要&#xff1a;从 Lyapunov 指数的定义出发&#xff1a;在常用计算最大 Lyapunov 指数的基础上&#xff0c;将自相关法和 G-P 法应用于小数 据量法中&#xff0c;得到了一种计算最大 Lyapunov 指数的改进小数据量法…

推特的算法规则你知道多少?

如果玩Twitter却不明白Twitter算法是如何运作的&#xff0c;就如同贸然出征却忘了带上武器。 社交媒体的算法正在成为你在平台中所见内容的核心&#xff0c;当知晓了该平台的推荐算法&#xff0c;自然也就知道发布什么样的内容有助于被更多用户看到。因此&#xff0c;了解了算…

Spring之依赖注入

文章目录前言一、set注入1.1 UserDao类&#xff1a;1.2 UserService类&#xff1a;1.3 spring.xml配置文件&#xff1a;1.4 测试类&#xff1a;1.5 执行结果&#xff1a;二、构造方法注入2.1 UserDao2.2 UserService类&#xff1a;1.3 spring.xml配置文件&#xff1a;2.4 测试类…

微服务改造过程中那些必须重视的问题

“微服务”近几年尤其火热&#xff0c;各大厂都在进行微服务化改造和微服务建设&#xff0c;想享受微服务化带来的好处以便对自己的系统进行改造。分布式实验室特约记者李鹏采访了广州轻阅科技系统架构师陈珙&#xff0c;就微服务与SOA的区别与联系、企业引入微服务会带来的问题…

Vue2:官方路由 Vue-Router 3.x

前端路由 前端路由&#xff1a;根据不同的url地址&#xff0c;页面上展示不同的内容&#xff08;根据url地址的不同分发到不同的组件。&#xff09; SPA 介绍 spa 是 single page application 简写&#xff0c;意思是单页面应用程序。Vue 适合开发 spa 类型的项目。 优点&…

Django 所带的用户auth_user的坑点,authenticate()校验一直为None,校验与创建所遇到的问题整理与解决

整理一下django中用户模块自定义model后登录的一些问题&#xff1a; 网上的报错解决不是万能方案&#xff0c;主要还是要自主分析原因&#xff0c;有的是有用但是导包之类的也要看清楚因为自己修改了所以有所变得&#xff0c;不自定义的话又不太好用。 在项目初期决定使用auth…