当前位置: 首页 > article >正文

Spring(一)

bean对象的存储和读取

1.创建一个bean对象,在java当中一个对象被使用多次,就可以称为Bean。

package com.spring.demo;

public class Student {
    public void sayHi(){
        System.out.println("hi student");
    }
}

2.将bean存储到Spring容器当中

<!-- 将 bean(com.spring.demo.Student)存到 Spring 容器中,它的名称叫做 student -->
    <bean id="student" class="com.spring.demo.Student"></bean>

解释说明:

3.从Spring容器当中读取bean对象

import com.spring.demo.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
        //1.创建Spring上下文
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");

        //2.从Spring容器当中获取到Bean对象
        Student student = (Student) context.getBean("student");

        //3.使用Bean对象
        student.sayHi();
    }
}

运行结果:

注意细节问题,如下图所示

除了上述使用的 ApplicationContext接口,还可以使用 BeanFactory接口来创建Spring上下文。

  //1.创建Spring上下文
        BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("spring-config.xml"));

        //2.从Spring容器当中获取到Bean对象
        Student student = (Student) beanFactory.getBean("student");

        //3.使用Bean对象
        student.sayHi();

运行结果:

问题:既然它们都能够实现同样的功能,为什么有了 ApplicationContext还要有 BeanFactory呢?

 

请看如下代码:

package com.spring.demo;

public class Student {
    public Student() {
        System.out.println("Student构造方法被执行");
    }

    public void sayHi() {
        System.out.println("hi student");
    }
}


public class App {
    public static void main(String[] args) {
        //1.得到Spring上下文
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
}

ApplicationContext运行结果:

得出结论:

ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");这行代码执行结束,就会加载对应的Bean对象(饿加载模式)。

对应的:使用BeanFactory下面行这行代码执行结束,并不会对构造方法进行初始化。

BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("spring-config.xml")); (懒加载模式)。


当程序执行到这行代码的时候才会有初始化的操作Student student = (Student) beanFactory.getBean("student");

ApplicationContext 和 BeanFactory的区别

 

1.从继承关系上来说:

 BeanFactory提供了基础的访问容器的能⼒,⽽ApplicationContext属于 BeanFactory 的⼦类,它除了继承了 
 BeanFactory 的所有功能之外,还添加了对国际化,支持资源访问⽀持、以及事件传播等⽅⾯的⽀持。

2.二者的加载时机不同:
ApplicationContext是饿加载,它会一次性将xml文件中的Bean对象进行加载,之后的读取效率会很高。而BeanFactory是懒加载,只有调用getBean的时候,才会去加载对应的Bean对象,因此效率较低。

3:从本质上来说,二者并没有谁好谁坏之分,他们测重点不同,ApplicationContext效率高是通过牺牲内存为代价的,而BeanFactory效率低的同时,也节约了内存空间。 

 

 

获取Bean对象的三种方式

1.通过名称获取

2.通过类型获取

通过类型获取引发的问题是:如果Spring容器当中一个类型存储了多个实例,那么使用类型获取就会抛NoUniqueBeanDefinitionException

3. 通过名称+类型获取

Student student = context.getBean("student", Student.class);

Spring 更简单的读取和存储对象

在 Spring 中使⽤注解可以更简单的存储和读取对象。

在进行Bean对象的存取的时候,需要做一下前置工作,配置扫描路径。想要将对象成功的存储到 Spring 中,我们需要配置⼀下存储对象的扫描包路径,只有被配置的包下的所有类,添加了注解才能被正确的识别并保存到 Spring 容器中。在 spring-config.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"
       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="com.java.demo"></content:component-scan>
</beans>

使用类注解(五大类注解)

  • @Controller:控制器:用于验证用户请求数据的合法性。(类似于安保系统)
  • @Service:服务:编排和调度具体执行方法的。(类似于客服中心)
  • @Repository:持久层:和数据库进行交互 (类似于执行者)
  • @Component:组件(工具类)
  • Configuration:配置项(项目中的一些配置)

@Controller实现Bean存储:

package com.java.demo;

import org.springframework.stereotype.Controller;

@Controller
public class StudentController {
    public void sayHi() {
        System.out.println("hi");
    }
}

注意问题:一定要把注解加上,不加注解会抛异常,如下图所以

读取Bean:

import com.java.demo.StudentController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
        //1.获取Spring上下文对象
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");

        //2.获取Bean
        StudentController studentController = context.getBean("studentController", StudentController.class);

        //3.使用Bean
        studentController.sayHi();
    }
}

@Service实现Bean存储

package com.java.demo;

import org.springframework.stereotype.Service;

@Service

public class StudentService {
    public void sayHi(){
        System.out.println("hi");
    }
}

读取Bean:

import com.java.demo.StudentService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
        //1.获取Spring上下文对象
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");

        //2.获取Bean
        StudentService studentService = context.getBean("studentService", StudentService.class);

        //3.使用Bean
        studentService.sayHi();
    }
}

剩下三个类注解,在使用上和上述两个注解的使用完全一样。

注意事项

  • 先配置扫描路径,在存放Bean到Spring容器中。
  • 在component-scan下不要忘记加五大类注解,否则将会抛异常。
  • <bean>标签可以和component-scan一起使用。
  • component-scan下的所有子包下的类只要加了五大类注解,同样可以将对象存储到Spring中
  • 五大类注解不可以不在component-scan包下。

五大类注解之间的关系

如下图所示:

<bean>可以和component-scan 一起使用

有时候,某个类放在扫描路径下觉得不合适,但又想将这个对象存放到Spring容器当中,为了满足这种场景,就需要扫描路径和传统的类名+classPath结合使用。

      为什么要有这么多注解呢? 

虽然它们都能实现相同的功能,但它们也有不同的之处,注解很重要的一个功能就是让开发者一看到注解,就知道这个注解的用途。比如:

  • @Controller:表示业务逻辑层
  • @Service:服务层
  • @Repository:持久层
  • @Configuration:配置层

程序的工程分层,调用流程如下:

阿里在标准分层的基础之上,又进行了划分 ,如下图所示:

Bean的命名规则

源码展示:

 

方法注解 @Bean

类注解是把注解加在类上,方法注解是将注解加在方法上。

有时候我们需要将一个对像作为返回值,然后交给Spring容器来托管,就可以使用这个@Bean。

代码实例:

1.先创建一个是实体类

package com.java.demo.entity;

public class User {
    private Integer uid;
    private String username;
    private Integer age;

    public Integer getUid() {
        return uid;
    }

    public void setUid(Integer uid) {
        this.uid = uid;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "uid=" + uid +
                ", username='" + username + '\'' +
                ", age=" + age +
                '}';
    }
}

 

2.将返回的对象存入Spring容器当中

package com.java.demo.component;

import com.java.demo.entity.User;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component
public class UserBeans {
    @Bean(name = {"u1","u2"})//Bean重命名
    public User user1() {
        User user = new User();
        user.setUsername("张三");
        user.setAge(18);
        user.setUid(1);
        return user;
    }
}


说明:虽然叫方法注解,但是它要搭配上类注解,才能成功的存入Spring容器当中。

3.从Spring容器当中取出bean对象

import com.java.demo.controller.UserController;
import com.java.demo.entity.User;
import com.java.demo.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

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

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

        System.out.println(user.toString());
    }
}


   说明;1.@Bean的命名规则和上述的五大类注解的命名规则不同。默认情况下@Bean存储对象的
          名称 = 方法名
      
        2.在使用Bean注解的时候,需要搭配上上述的五大类注解一起使用。

        3.@Bean可以重命名,当@bean进行重命名之后,默认方法名的方式无法获取到bean对象。




      

 


 

 

对象注入 

 

//对象注入:将存储在Spring容器当中的bean对象,注入到当前类中。对象注入有三种方式:


//1.属性注入

@Autowired
 private UserService userService;


//2.setter注入

private UserService userService;

   @Autowired
   public void setUserService(UserService userService) {
       this.userService = userService;
   }



//3.构造方法注入


 private UserService userService;

    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
        userService.age = 20;
    }

 

 

三种注入对象的优缺点分析:

1.属性注入:

 

2.setter注入:

 

 

3.构造方法注入:

 


http://www.kler.cn/a/583871.html

相关文章:

  • 工具(十二):Java导出MySQL数据库表结构信息到excel
  • 5G/6G通信技术
  • 便利店商品推荐数字大屏:基于python和streamlit
  • js下载blob二进制文件流 预览
  • 瑞芯微RK3588安卓使用fastboot分区烧录
  • 江科大51单片机笔记【12】AT24C02(I2C总线)
  • 浙江大学第四讲:DeepSeek模型优势:算力、成本角度解读(含PPT及直播回放)(文末附链接下载)
  • 前端面试:px 如何转为 rem
  • DrBioRight2.0:用于癌症蛋白组分析的生物学聊天机器人
  • 【Linux篇】进程状态(僵尸进程,孤儿进程),优先级与调度机制
  • 内检实验室lims系统在电子设备制造行业的应用
  • 中小型企业如何利用远程控制方案来降低40%运维成本的
  • 麒麟v10 ARM64架构系统升级mysql数据库从mysql-5.7.27到mysql-8.4.4图文教程
  • Django系列教程(7)——路由配置URLConf
  • 使用AI一步一步实现若依前端(12)
  • 快读模板(Java)
  • 【后端开发面试题】每日 3 题(十二)
  • 【从零开始学习计算机科学】数据库系统(九)DBMS的体系结构
  • 复变函数摘记1
  • 在微信小程序或前端开发中,picker 和 select 都是用户交互中用于选择的组件,但它们在功能、设计和使用场景上有一定的区别