Java研学-spring框架(二)
作者:mmseoamin日期:2024-01-25

五 Bean 概述

1 概述

  在Spring框架中,Bean是核心概念之一,是Spring装配的组件模型。一切实体类都可以配置成一个Bean,进而就可以在任何其他的Bean中使用。一个Bean也可以不是指定的实体类,这就是抽象Bean。

  在Spring中,构成应用程序主干并由Spring IoC容器管理的对象称为bean。bean是一个由Spring IoC容器实例化、组装和管理的对象。

  bean属性和作用:

  id:给对象在容器中提供一个唯一标识。用于获取对象。

  class:指定类的全限定类名。用于反射创建对象。默认情况下调用无参构造函数。

  scope:指定对象的作用范围。在Spring2.0之前,Bean只有两种作用域,即Singleton(单例)和non-Singleton(也称prototype)。Spring2.0以后,增加了session、request和global session三个专用于Web应用程序上下文的Bean。

  同时,元素是Spring配置文件的根元素,元素可以包含多个子元素,每个元素可以定义一个Bean实例。每一个Bean对应Spring容器里的一个Java实例定义Bean时通常需要指定两个属性:Id和Class

2 bean的创建时机

  启动 Spring 容器的时候就会创建所有的 bean(单例,可在实体类的无参构造中添加输出方法进行测试)

3 bean的实例方式

① 构造器实例化 – 无参构造器

实体类 – Student

public class Student{
    public Student(){
        System.out.println("实例化");
    }
}

配置文件 – spring-student.xml



    
    

测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-student.xml")
public class StudentTest {
    @Autowired
    private Student s1;
    @Test
    public void student_test1(){
        System.out.println(s1);
    }
}

② FactoryBean 接口实例化

实体类 – Student

public class Student{
    public Student(){
        System.out.println("实例化");
    }
}

实现类 – StudentFactoryBean

// BeanFactory是一个工厂类接口
// 主要用于管理Bean,包括实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。
// 它通常用于从XML配置文件中加载bean定义,并且根据这些定义创建bean实例。
public class CatFactoryBean implements FactoryBean {
    @Override
    public Student getObject() throws Exception {//返回实体类对象
        return new Student();
    }
    @Override
    public Class getObjectType() {
        return Student.class;
    }
}

配置文件 – spring-student.xml



    

测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-student.xml")
public class StudentTest {
    @Autowired
    private Student s1;
    @Test
    public void student_test1(){
        System.out.println(s1);
    }
}

六 bean 作用域

1 介绍

  Bean的作用域指的是Bean在Spring整个框架中的生命周期和作用范围。

2 分类

  ① Singleton:单例作用域。该作用域下,Spring容器中只存在一个Bean实例,所有的请求都返回同一个Bean实例。这是Spring的默认选择的作用域,适用于不需要频繁新建和销毁Bean的情况。

  ② Prototype:原型作用域。每次请求时都会创建一个新的Bean实例。这种作用域下,Bean的生命周期很长,不易回收,通常需要进行额外的清除处理。

  ③ Request:请求作用域。每个HTTP请求都会创建一个新的Bean实例,该Bean实例仅在当前请求内有效。适用于一次HTTP请求和响应的共享Bean。

  ④ Session:会话作用域。每个HTTP会话都会创建一个新的Bean实例,该Bean实例仅在当前会话内有效。适用于用户回话的共享Bean,比如记录一个用户的登陆信息。

  ⑤ Application:全局作用域。一个Bean定义对应于单个ServletContext的生命周期。适用于Web应用的上下文信息,例如记录一个应用的共享信息。

  ⑥ WebSocket:HTTP WebSocket作用域。一个Bean定义对应于单个WebSocket的生命周期。适用于WebSocket的会话中,保存了一个Map结构的头信息,将用来包裹客户端信息头。

3 语法

  不配置为 singleton,当 scope 为 prototype 时,容器启动不会创建该 bean,在调用getBean方法时才会创建对象


七 bean的初始化销毁

1 实体类 – MyDatasource

public class MyDatasource {
    public MyDatasource(){
        System.out.println("bean创建,调用无参构造执行");
    }
    public void getConnection(){
        System.out.println("创建连接对象执行.....");
    }
    public void init(){
        System.out.println("init初始化对象执行");
    }
    public void destroy(){
        System.out.println("对象销毁执行destroy方法.....");
    }
}

2 配置文件 – spring-datasource.xml



    
    

3 测试方法

    @Test
    public void test_bean(){
        ClassPathXmlApplicationContext context= new ClassPathXmlApplicationContext("spring-datasource.xml");
        MyDatasource dataSource = (MyDatasource) context.getBean("dataSource");
        // 获取连接对象
        dataSource.getConnection();
        // 执行销毁操作
        context.close();
    }

  正常关闭容器,才会执行 bean 的配置的 destroy-method 方法。若 bean 的 scope 为 prototype 的,则容器只负责创建和初始化,它并不会被 Spring 容器管理(不需要存起来),由用户自己处理。bean 作用域为 prototype 的即使配置了 destroy-method 也不会被调用。

八 DI概述

1 介绍

  Spring 创建对象的过程中,将对象依赖属性通过配置设值给该对象。

2 注入方式

  ① setter 注入(属性注入),该类需提供对应的 setter 方法

  ② 构造器注入:类中必须有无参构造和有参构造

实体类

public class Employee{
    private String name;
    public Employee() {}
    public Employee(String name) {
        this.name = name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

测试

public class EmployeeTest {
    @Test
    public void test() {
        User u1 = new User();
        // 属性注入
        u1.setName("叶凡"); 
        // 构造器注入
        User u2 = new User("石昊"); 
        // 注入值可为常量 bean等等
    }
}

3 Setter注入 – 常量注入

  常量指基本数据类型及其包装类,String,BigDecimal等,Bean指的是给对象注入值的是容器中的另外一个对象

① 实体类 – Employee

public class Employee {
    private String name;
    private Integer age;
    private String phone;
    private Person person;
    public Person getPerson() {
        return person;
    }
    public void setPerson(Person person) {
        this.person = person;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", phone='" + phone + '\'' +
                ", person=" + person +
                '}';
    }
}

② 被注入的实体类 – Person

public class Person {
    @Value("李四")
    private  String name;
    public  Person(){
        System.out.println("无参构造");
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void doWork(){
        System.out.println(this.name+"要出去玩");
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}

③ 配置文件 – spring-emp.xml



    
    
        
    
    
    
        
        
        
        
        
        
    
    
        
        
        
        
    

④ 测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-emp.xml")
public class EmpTest {
    @Autowired
    private Employee emp1;
    @Test
    public void emp_test(){
        System.out.println(emp1);
    }
}

4 setter注入 – Bean注入

① dao层

// 接口
public interface EmployeeDao {
}
// 实现类
public class EmployeeDaoImpl implements  EmployeeDao{
}

② service层

// 接口
public interface EmployService {
}
// 实现类
public class EmployServiceImpl implements EmployService{
    private EmployeeDao employeeDao;
    public void setEmployeeDao(EmployeeDao employeeDao) {
        this.employeeDao = employeeDao;
    }
}

③ xml

	
    
    
    
    
        
    

5 构造注入

① 实体类 – Student

public class Student {
    private  String name;
    private  Long sn;
    private  String phone;
    private Date birthday;
    public Student() {}
    public Student(String name, Long sn, String phone, Date birthday) {
        this.name = name;
        this.sn = sn;
        this.phone = phone;
        this.birthday = birthday;
    }
    public Student(String name, Long sn, String phone) {
        this.name = name;
        this.sn = sn;
        this.phone = phone;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", sn=" + sn +
                ", phone='" + phone + '\'' +
                ", birthday=" + birthday +
                '}';
    }
}

② 配置文件 – spring-student.xml

 
 	
    
        
        
        
    
    
        
        
        
    
    
        
        
        
    
    
    
    
        
        
        
        
    

③ 测试方法

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-student.xml")
public class StudentTest {
	// 1 2 3 4 依次注入
    @Autowired
    private Student student4;
    @Test
    public void student_tes() {
        System.out.println(student4);
    }
}

九 DI 注解

1 Autowired注解

  主要用于 Spring 框架中,用于完成自动装配。它可以被用于成员变量、方法和构造函数上。

  ① 可以让 Spring 自动的把属性或字段需要的对象找出来,并注入到属性上或字段上。

  ② 可以加在字段或者 setter 方法上面。

  ③ 可以同时注入多个对象,一个对象对应一个注解

  ④ 可以注入一些 Spring 内置的重要对象,比如 BeanFactory,ApplicationContext 等。

  ⑤ 默认情况下 Autowired 注解必须要能找到对应的对象,否则报错。通过 required=false 来避免这个问题:@Autowired(required=false)。(默认为true表示必须找到该对象否则报错)

  ⑥ Autowired 注解寻找 bean 的方式:

    1.首先按照依赖对象的类型找,若找到,就是用 setter 或者字段直接注入。

    2.如果在 Spring 上下文中找到多个匹配的类型,再按照名字去找,若没有匹配报错。

    3.可以通过使用 @Qualifier(“other(bean的id)”) 标签来规定依赖对象按照 bean 的 id 和 类型的组合方式去找。

实体类

public class Teacher{
	@Autowired
	private Student student ;
	@Override
	public String toString() {
		return "Teacher的学生有[student =" + student + "]";
	}
}

配置文件



测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:04.anno.xml")
public class TeacherTest {
	@Autowired
	private Teacher teacher;
	@Test
	public void test() {
		System.out.println(teacher);
	}
}

2 Resource 注解

  @Resource 注解用于在 Java 应用程序中实现依赖注入。它是 Java EE 规范的一部分,并被 Spring 框架广泛使用。使用 @Resource 注解,Spring 容器会在运行时查找匹配的 bean,可以将一个对象注入到另一个对象的字段、构造函数或方法中。这个过程通常由 Spring 容器管理,通过扫描带有特定注解的类和方法来实现。

  ① 可以让 Spring 自动的把属性或字段需要的对象找出来,并注入到属性上或字段上。

  ② 可以贴在字段或者 setter 方法上面。

  ③ 可以注入一些 Spring 内置的重要对象,比如 BeanFactory,ApplicationContext 等。

  ④ Resource 注解必须要能找到对应的对象,否则报错。

  ⑤ Resource 注解寻找 bean 的方式:

    1.首先按照名字去找,如果找到,就使用 setter 或者字段注入。

    2.若按照名字找不到,再按照类型去找,但如果找到多个匹配类型,报错。

    3.可以直接使用 name 属性指定 bean 的名称(@Resource(name=“”));但若指定的 name,就只能按照 name 去找,若找不到,就不会再按照类型去。

将 Autowired 注解demo 中的 @Autowired 改为 @Resource 即可

3 Value注解

  在Spring框架中,@Value注解用于给基本类型的属性赋值。它允许从配置文件(如.properties或.yml文件)中读取值,并注入到属性中。@Value注解可以用于方法上或属性上。

public class Student{
	@Value("大黄")
    private String name;
	@Override
	public String toString() {
		return "[name=" + name + "]";
	}
}
// application.properties文件内容
database.url=jdbc:mysql://localhost:3306/mydb  
database.username=root  
database.password=secret
// value注入
@Value("${database.url}")  
private String databaseUrl;  
@Value("${database.username}")  
private String databaseUsername;  
@Value("${database.password}")  
private String databasePassword;

  这样,Spring会在启动时从配置文件中读取相应的值,并将其注入到这些属性中。此外,@Value注解也可以用于表达式语言(SpEL)表达式,用于获取bean的属性或调用bean的方法

@Value("${key}")  
private String valueFromProperty;
// 或者
@Value("#{configProperties['key']}")  
private String valueFromConfig;

十 IoC 注解

1 介绍

  将标注的类放入spring容器,交给spring管理,四个注解的功能相同,用于标注不同类型的类(不需再配置xml的bean了)

注解说明
@Repository用于标注数据访问组件,即 DAO 实现类上。
@Service用于标注业务层实现类上。
@Controller用于标注控制层类上。
@Component当不是以上的话,可以使用这个注解进行标注。

2 例子

@Component
public class Student{
	@Value("大黄")
    private String name;
	@Override
	public String toString() {
		return "[name=" + name + "]";
	}
}

十一 注解补充

1 介绍

注解说明
@Scope贴在类上,标明 bean 的作用域,类似bean标签的scope属性
@PostConstruct贴在方法上,标明 bean 创建完后调用此方法,类似bean标签的init-method属性
@PreDestroy贴在方法上,标明容器销毁时调用此方法,类似bean标签的destroy-method属性

2

实体类

@Component
@Scope("prototype")
public class MyDataSource {
	public MyDataSource() {
		System.out.println("bean创建,调用无参构造执行");
	}
	public void getConnection() {
		System.out.println("创建连接对象执行.....");
	}
	@PostConstruct
	public void init() {
		System.out.println("init初始化对象执行");
	}
    @PreDestroy
	public void close() {
		System.out.println("对象销毁执行destroy方法....");
	}
}

测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("spring-datasource.xml")
public class MyDataSourceTest {
	@Autowired
	private MyDataSource dataSource;
	@Test
	public void test() {
		dataSource.getConnection();
	}
}
 

上一篇:HNU-数据挖掘-作业1

下一篇:Gradle 笔记