Spring的创建与Bean对象的存取

文章目录:一.Spring项目的创建1.先创建maven项目

                                                      2.添加国内源

                                                      3.添加spring依赖

                                                      4.创建spring配置文件

                                                       5.创建启动类

                   二.Bean对象的创建和读取1.Bean对象的创建与存储方式(1)类注解

                                                                                                                      (2)方法注解

                                                                                                                         (3)<bean>格式

                                                               2.Bean对象的获取方式(1)通过id

                                                                                                       (2)通过类名

                                                                                                       (3)id+类名

                                                                                                         (4)注解@Autowired                                                                   

                                                                                                (5)@Autowired @Resource区别             

一.Spring项目的创建

1.先创建一个maven项目

2.添加国内源

查看Local reposittory目录下是否有settings这个文件

将settings.xml文件里在<mirros>里面添加阿里云镜像

 

3.添加spring-content依赖

4.添加配置文件在resources底下

 在文件里添加如下内容

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:content="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <content:component-scan base-package="kale"></content:component-scan>
    <!--<bean id="beanlife" class="kale.pole.Beanlife" init-method="init" destroy-method="preDestroy"> </bean>-->

</beans>

5.添加启动类

二.Bean对象的创建与读取

1.Bean对象的创建

我们先来创立一个Student类

package spring;

public class Student {
    public String name="网红";
    public  int id=3;
    public int  score=97;
    String s=new String();
    public Student()
    {

        System.out.println("学生初始化");
    }
    public void say()
    {
        System.out.println("你好学生");
    }
}

在resources文件底下,新建一个spring-config(文件名可以随意起) xml文件

在xml文件里引入:

将bean对象存储到spring容器中

然后我们就可以在里面注册bean 对象,我们将student对象注册到spring中

<bean id="student" class="spring.Student"></bean>

 其中 class后面需要写  包名+类名

2.从spring容器中获取bean

1.因为我们是在spring中注册bean,如果我们想要获取到,我们需要先获取到spring上下文,这里我们就涉及到两个类(ApplicationContext、BeanFactory)

2.然后根据注册的id,来获取对应的bean对象

 public static void main(String[] args) {
        (1)//获取spring上下文
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
        (2)//根据id来取容器里对应的bean对象
       Student result=(Student)context.getBean("student");
        result.say();

    }
 

  3.ApplicationContext  BeanFactory有什么区别:

我们再来创建一个Teacher类,然后在spring中将实例化的对象给注册到里面去

package spring;

import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;

public class Teacher {
    public Teacher()
    {
        System.out.println("教师初始化");
    }
    public void say()
    {
        System.out.println("你好,教师");
    }

}
<bean id="teacher" class="spring.Teacher"></bean>

我们先来用 ApplicationContext 来演示

 public static void main(String[] args) {
        
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
       

    }

 

我们可以发现当用去获取上下文时,spring中所有的类都被加载了,也就是在这时我们才真正的去创建bean对象,一开始在spring-config.xml中我们只是去注册、声明bean对象。

我们再来看一下,BeanContext

 public static void main(String[] args) {
        BeanFactory context=new XmlBeanFactory(new ClassPathResource("spring-config.xml"));
}
       

    

当我们去运行这个程序的时候,发现什么都没有

 public static void main(String[] args) {
        BeanFactory context=new XmlBeanFactory(new ClassPathResource("spring-config.xml"));
        Student result=(Student)context.getBean("student");

    }

 这时我们再调用一下getBean()方法,我们再运行程序

 由此我们可以得出当我们去使用BeanFactory的时候,我们发现只有当我们去取这个对象的时候,我们才会真正去加载并创建它

区别:(1)BeanFactory是 ApplicationContext的父类,其功能和方法相较于ApplicationContext要更少,这样效率、性能会高

        (2)ApplicationContext一次加载并实例化所有的Bean对象,而BeanFactory是能用到那个Bean对象再去加载初始化这个对象的,这样节省空间,但效率低

4.Spring存取对象的基本流程:

1.Spring读取Bean流程:先扫描xml文件配置,从配置中或注解中获取Bean对象的定义信息,然后把它注册到Spring容器中

2.Spring加载并实例化Bean:先给Bean对象分配空间,然后进行初始化,然后把它设置到Spring容器中

5.获取bean对象的几种方式

(1)通过id名称获取bean

 public static void main11(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
       Student result=(Student)context.getBean("student");
        result.say();

    }

(2)通过类名获取bean:

public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
        Student result=context.getBean(Student.class);
        result.say();
    }

 当我们通过类名的方式去获取对象的时候,我们发现这个时候,我们不用再进行强转成Student类型了

但是这种方式存在一个问题,如果我们再注册一个Student类的对象在里面

 <bean id="student" class="spring.Student"></bean>
      <bean id="stu" class="spring.Studedt"></bean>
       <bean id="teacher" class="spring.Teacher"></bean>

这时我们再去通过这种方式获取这就存在问题了。

(3)正确的方式应该是通过  id+类名的方式

 public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        Student student1 = context.getBean("student", Student.class);
        Student student2 = context.getBean("stu", Student.class);
        student1.say();
        student2.say();
    }

 

(4)更简单的存储Bean对象的方式,添加类注解

五大类注解:1.@Controller   (控制器,用来验证前端传来的数据是否正确,如果不正确,返回false)防止别人恶意访问程序,相当于安保系统

2.@Service 服务:负责调度和提供一些方法,但是不实际执行,相当于客服中心

 3.@Repository 持久层:和数据层交互,负责实际执行

 4.@Component   组件工具类

 5.@Configuration   配置项(项目当中的一些配置)

在这里边Compoent是所有这几个类的父类,其他的四个类都继承了这个类,我们随便打开其他四个类里面的一个类看看:

通过在在类外添加注解的方式也能存储Bean对象,但是我们需要在spring-conflig.xml中增加

  <content:component-scan base-package="com.gather"></content:component-scan>

base-package表明类所在的包

package com.gather;

import org.springframework.context.annotation.Configuration;

@Configuration
public class Student{
    public void say()
    {
        System.out.println("hello student");
    }
}

像这种添加类注解的方式,我们用getBean()的方式来获取的话,那么里面的参数应该如何写呢?其实也是一种类似于Bean名称+类名的方式,如果类名第一个字母大写的话,我们只需把第一个字母变成小写

public class Text {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-conflig.xml");
        Student student=(Student) context.getBean("student",Student.class);
        student.say();

    }
}

在这里我们看到如果类名第一个字母大写的话,id直接将类名第一个字母小写即可,

如果我们建的类名前两个都是大写的话,这样就不可以了

public class POlice {
    public void say()
    {
        System.out.println("hello police");
    }
}
public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-conflig.xml");
        POlice police=context.getBean("police",POlice.class);
        police.say();
    }

 如果id直接也是把第一个字母小写的话,我们发现会报错,

 这时候id应该直接写类名

 public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-conflig.xml");
        POlice police=context.getBean("POlice",POlice.class);
        police.say();
    }

 那么为啥是这样呢?我们来看一下这里相关的源码:

Bean命名规则:首字母默认是小写的,如果首字母第一个大写 ,Bean名称需要将第一个字母小写,如果前两个字母都是大写,那么Bean名称就是类名。

在这里我们还需要注意一个问题:

如果在spring-conflig.xml里只有这一种通过添加注解的方式来存取Bean对象

<content:component-scan base-package="com.gather"></content:component-scan>

我们要存取和Bean对象与之对应的类必须在这个包底下或者在这个包的子目录里,另外如果想要访问这个包底下与之对应的所有Bean对象,这些类都要加注解,举个例子:

 因为Farmer这个类没在com.gather这个包底下,也不在这个包的子包底下,所以相当于我们没把它注册到Spring容器中,所以就取不到这个对象

那应该如何解决呢?

我们在spring-conflig.xml再加一行Bean注册内容即可

 <bean id="farmer" class="Farmer"></bean>
public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-conflig.xml");
        Farmer farmer=context.getBean("farmer",Farmer.class);
        farmer.say();

    }

通过在方法上加Bean注解的方式将Bean对象存储在服务器上,但是在类上我们要加上类注解,因为这样我们是存在一些类不需要去存储在Spring中,这样再去读取扫描和配置文件的时候,可以快速的定位存储在Spring中的类,方便快速取出对象,这样可以提高性能。

@Configuration
public class Use2 {
    @Bean
    public User getuser2()
    {
        User user=new User();
        user.name="小凯";
        user.age=5;
        return user;
    }
}

但是要注意这里的方法名必须是要存储Bean对象的类名

 public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-conflig.xml");
        User user=context.getBean("getuser2",User.class);
        System.out.println(user.name);
    }

这里要注意getBean()方法里的第一个参数是方法名 

 我们来看一下打印信息

getBean()方法里面第一个参数也就是Bean名称是一个方法名,感觉怪怪的,其实我们是可以重新起一个名字的

@Configuration
public class User1 {
    @Bean(value = "user2")
    public User getuser2()
    {
        User user=new User();
        user.name="小凯";
        user.age=5;
        return user;
    }

}

 也就是在Bean注解之后用value重新起一个名,getBean()方法里第一个参数也就可以写这个名了

 User user=context.getBean("user2",User.class);

但是这里要注意如果重新起了名,getBean()方法里第一个参数就不能再用原来的方法名了(getuser2) 

大家在这里想一个问题,如果我们再在另一个类里面写一个和User1里面一模一样的方法,那么当我们再去取得时候

@Configuration
public class User2 {
    @Bean//(value="user7")
    public User getuser2() {

        User user = new User();
        user.name = "小中";
        user.age = 5;
        return user;


    }
}
 public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-conflig.xml");
        User user=context.getBean("getuser2",User.class);
        System.out.println(user.name);
    }

这取决于谁先注入,谁先被加载,谁后注入,后注入的会覆盖先注入的,我们再来写段代码看看,

我们在两个类前面分别加上两个@Order(10) 、@Order(20)  这里的注解表示的是谁先注入,数字越小表示注入的越早,一开始是User1里面的先注入,当我们把数值改一@Order(20)@Order(10)

这时就会产生不同的结果了。

取Bean更简单的方式使用@AutowiredResource

@Autowired 注解表示将需要的对象从Spring容器里取出来,

1.属性注入

我们先建立一个Police类

@Configuration
public class Police {
    public String name;
    public int age;
    public void say()
    {
        System.out.println("hello police");
    }
}

然后再创建一个UsePolice类,我们通过属性注入的方式将Police对象注入,

@Configuration
public class UsePolice {
    @Autowired
    Police police;
    public void getpolice()
    {

        police.say();
    }

}

然后我们拿到UsePolice这个类型的对象 

 public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-conflig.xml");
        UsePolice usePolice=context.getBean("usePolice",UsePolice.class);
        usePolice.getpolice();
    }

属性注入的优点:简单方便      弊端:(1)不符合单一设计的原则,我们可以将多个类型的对象共同注入(2)不能注入被final修饰的对象

因为final修饰的变量要么在后面直接赋值,要么利用构造方法赋值。

(3) 只适用于Ioc容器,不具备通用性

2.Setter注入

@Configuration
public class UsePolice2 {
     public Police police;
     @Autowired
     public void setPolice(Police police) {
        this.police = police;
    }

    public void getpolice()
    {
        police.say();

    }


}

Setter方法注入的优点:(1)符合单一设计的原则    缺点:(1)不能注入被final修饰的对象

(2)使用Setter注入的对象可能被修改   比如我们在getPolice()方法里将police置为null

@Configuration
public class UsePolice2 {
     public Police police;
     @Autowired
     public void setPolice(Police police) {
        this.police = police;
    }

    public void getpolice()
    {
        this.police=null;
        police.say();

    }
}



3.构造方法注入

@Component
public class UsePolice3 {
    public Police police;
    @Autowired
    public UsePolice3(Police police)
    {
        this.police=police;
    }
    public void getpolice()
    {
        police.say();
    }

}

构造方法注入的特点:如果当前类里面只有一个构造方法的话,那么@Autowired可以被省略

构造方法注入优点分析:1.能注入被final修饰的对象

2.构造方法只执行一次,注入对象不会再被修改

3.构造方法注入不止适用于Ioc容器,具有通用性。 

4.构造方法注入会将注入的对象完全初始化

缺点:构造方法里可以传多个参数,可能会违背单一设计原则。

与@Autowired注解作用差不多的还有@Resource注解

@Resource同样可以属性注入和Setter注入,但是如果是构造方法注入就会报错

 接下来我们来思考一个问题:如果有两个Police对象,这时注入的是谁呢?我们启动一下

@Component
public class Useuser4 {
    @Bean(value="police1")
    public Police getpolice()
    {
        Police police=new Police();
        police.name="小海";
        police.age=9;
        return police;

    }
    @Bean
    public Police getpolice2()
    {
        Police police =new Police();
        police.name="小小";
        police.age=9;
        return police;
    }
}

Component
public class Usepolice {
    @Resource
    public Police police;

    public void say()
    {
       police.say();
       System.out.println(police.name);
    }

}
 public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-conflig.xml");
        Usepolice useuser4=context.getBean("usepolice",Usepolice.class);
        useuser4.say();
    }

打印结果:

 我们发现会报错,这是因为Resource先根据名称去查,然后再根据类型去查,

这里的名称也就是police ,我们发现注册的两个Police实例都不是这个名称,然后再根据Police类型去找,发现两个Police实例也不是以Police为名称的

这个问题的解决办法就是在Resource后面加上具体的Bean对象的名称

 @Resource(name="police1")
    public Police police;

这时候就指定是注入police1这个对象了

 那使用@Autowired能不能指定指定的对象呢?其实也是可以的

 @Autowired
    @Qualifier(value="police1")

总结:@Resource注解和@Autowired的区别

(1)@Autowired来自Spring  @Resource来自jdk的注解

  (2)@Autowired 支持属性注入、Setter注入、和构造方法注入,@Resource不支持构造方法注入

 (3)相较于@Autowired@Resource可以设置更多的参数可以在后面指定name,依次来获取Bean

 Bean的作用域

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【从零开始学Skynet】基础篇(五):简易聊天室

在游戏中各玩家之间都可以进行聊天之类的交互&#xff0c;在这一篇中&#xff0c;我们就来实现一个简易的聊天室功能&#xff0c;这在上一篇代码的基础上很容易就能实现。1、功能需求 客户端发送一条消息&#xff0c;经由服务端转发&#xff0c;所有在线客户端都能收到&#xf…

redis网络模型

用户空间和内核空间IO五种IO模型阻塞IO非阻塞IOIO多路复用selectpollepollweb服务流程信号驱动IO异步IOIO模型比较redis网络模型redis为什么是单线程redis单线程网络模型流程用户空间和内核空间 为安全&#xff0c;将用户应用和系统应用分隔开&#xff0c;产生用户空间和内核空…

OpenTex 企业内容管理平台

OpenText 企业内容管理平台 将内容服务与领先应用程序集成&#xff0c;弥合内容孤岛、加快信息流并扩大治理 什么是内容服务集成&#xff1f; 内容服务集成通过将内容管理平台与处于流程核心的独立应用程序和系统连接起来&#xff0c;支持并扩展了 ECM 的传统优势。 最好的内…

Flutter Web 开发实践与优化

一,Flutter Web架构 目前,除了可以支持Android、iOS移动跨平台开发之外,Flutter还支持macOS、Windows、Linux和Web等多个跨平台的开发。可以说,作为一款先进的跨平台开发框架,Flutter已经真正意义上实现了“一次编写,处处运行”的美好愿景。 众所周知,Dart 语言存在之…

事件触发模式 LT ET ?EPOLLIN EPOLLOUT 各种情况总结。【面试复盘】【学习笔记】

麻了&#xff0c;对 epoll 的触发机制理解不深刻…面试又被拷打了… 下面总结一下各种情况&#xff0c;并不涉及底层原理&#xff0c;底层原理看这里。 文章结构可以看左下角目录、 有什么理解的不对的&#xff0c;请大佬们指点。 先说结论&#xff0c;下面再验证&#xff…

package-cli-service,为构建发布npm包提供完整的工作流

package-cli-service 介绍 package-cli-service 是一个开发环境依赖。它是一个 npm 包&#xff0c;局部安装在每个 create-package-tools 创建的项目中。 package-cli-service 是构建于 rollup 和 webpack 之上的。它包含了&#xff1a; 一个针对绝大部分 package 优化过的内…

013 - C++引用

本期我们要讲的是 C 中的引用。 上期我们讨论了指针&#xff0c;如果你没有看过那期内容&#xff0c;你一定要回去看看&#xff0c;因为引用实际上只是指针的扩展&#xff0c;你至少需要在基本层面上理解指针是如何工作的&#xff0c;然后才能继续学习本期的内容&#xff0c;本…

MySQL索引数据结构入门

之前松哥写过一个 MySQL 系列&#xff0c;但是当时是基于 MySQL5.7 的&#xff0c;最近有空在看 MySQL8 的文档&#xff0c;发现和 MySQL5.7 相比还是有不少变化&#xff0c;同时 MySQL 又是小伙伴们在面试时一个非常重要的知识点&#xff0c;因此松哥打算最近再抽空和小伙伴们…

Golang数据类型比较

直接使用比较的情况 分类说明是否能比较说明基本类型整型&#xff08; int/uint/int8/uint8/int16/uint16/int32/uint32/int64/uint64/byte/rune等&#xff09;浮点数&#xff08; float32/float64&#xff09;复数类型&#xff08; complex64/complex128&#xff09;字符串&a…

Linux查看端口

目录 1.查看已知端口的使用情况 2.查看所有端口的占用情况 3.查看占用端口的程序的进程号 4.杀死进程号 1.查看已知端口的使用情况 #例:8080 可使用命令: netstat -anp | grep 8080 结果如下: 还可以使用这条命令: netstat -tln | grep 8080 结果如下: 区别:第一条命令后面显示…

NumPy 秘籍中文第二版:十二、使用 NumPy 进行探索性和预测性数据分析

原文&#xff1a;NumPy Cookbook - Second Edition 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 在本章中&#xff0c;我们涵盖以下秘籍&#xff1a; 探索气压探索日常气压范围研究年度气压平均值分析最大可见度用自回归模型预测气压使用移动平均模型预测气压研究年…

爱智EdgerOS之深入解析离线下载任务

一、需求分析 在日常使用计算机的过程中&#xff0c;看到喜欢的资源不可避免地想把它下载到我们的设备上保存下来&#xff0c;比如图片&#xff0c;音视频资源&#xff0c;文档资源等&#xff0c;基于这种应用场景&#xff0c;现在来看看在爱智设备上可以如何实现呢&#xff1…

76-TCP协议,UDP协议以及区别

TCP协议,UDP协议,SCTP协议一.TCP协议1.什么是TCP协议2.TCP协议的特点3.TCP头部结构4.TCP状态转移5.TCP超时重传二.UDP协议1.什么是UDP协议2.UDP协议的特点三.TCP和UDP的区别一.TCP协议 1.什么是TCP协议 TCP(Transmission Control Protocol)协议即为传输控制协议,是一种面向连…

2023-04-12 面试中常见的数组题目

数组中的问题其实最常见 通过基础问题&#xff0c;掌握写出正确算法的“秘诀”巧妙使用双索引技术&#xff0c;解决复杂问题对撞指针- 滑动窗口 1 从二分查找法看如何写出正确的程序 本节学习重点&#xff1a;处理边界问题&#xff01; 1.确定边界范围方法&#xff0c;先用区…

微服务架构-服务网关(Gateway)-权限认证(分布式session替代方案)

权限认证-分布式session替代方案 前面我们了解了Gateway组件的过滤器&#xff0c;这一节我们就探讨一下Gateway在分布式环境中的一个具体用例-用户鉴权。 1、传统单应用的用户鉴权 从我们开始学JavaEE的时候&#xff0c;就被洗脑式灌输了一种权限验证的标准做法&#xff0c;…

Elasticsearch:集群管理的一些建议

在之前的文章 “Elasticsearch&#xff1a;集群管理” &#xff0c;我们对集群管理做了一些介绍。在今天的文章中&#xff0c;我们接着来聊一下有关配置的方面的问题。这在很大程度上取决于你的用例&#xff0c;是索引还是搜索繁重。 我们将在这里讨论在集群设置方面我们需要关…

Leetcode.130 被围绕的区域

题目链接 Leetcode.130 被围绕的区域 mid 题目描述 给你一个 m x n的矩阵 board&#xff0c;由若干字符 X和 O&#xff0c;找到所有被 X围绕的区域&#xff0c;并将这些区域里所有的 O用 X填充。 示例 1&#xff1a; 输入&#xff1a;board [[“X”,“X”,“X”,“X”],[“X…

「Cpolar」使用Typecho搭建个人博客网站【内网穿透实现公网访问】

&#x1f482;作者简介&#xff1a; THUNDER王&#xff0c;一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学本科在读&#xff0c;同时任汉硕云&#xff08;广东&#xff09;科技有限公司ABAP开发顾问。在学习工作中&#xff0c;我通常使用偏后端的开发语言A…

在 Python 中计算两个数字之间的百分比

要计算两个数字之间的百分比&#xff0c;请将一个数字除以另一个数字&#xff0c;然后将结果乘以 100&#xff0c;例如 (30 / 75) * 100。这显示第一个数字占第二个数字的百分比。 在示例中&#xff0c;30 是 75 的 40%。 def is_what_percent_of(num_a, num_b):return (num_a…

基于SVG的HMI组件

人机界面是自动化领域不可或缺重要组成部分。人机界面系统的设计看上去并没有太大的技术门槛&#xff0c;但是设计一个HMI系统的工作量是巨大的&#xff0c;如果你没有足够的耐心和精力是难以完成一个通用HMI系统的。构建UI控件库就是一个似乎永远完不成的事情&#xff0c;用户…