Java研学-spring框架(二)

五 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

<?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">
    <!--使用构造方法实例化:Student s1=new Student ();-->
    <bean id="student" class="cn.tj.domain.Student"></bean>
</beans>

测试类

@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

<?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="student" class="cn.tj.domain.StudentFactoryBean"></bean>
</beans>

测试类

@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 id="" class="" scope="作用域"/>

七 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

<?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">
    <!--创建数据源对象 init destroy是初始化与销毁所调用的方法(在实体类中)-->
    <bean id="dataSource" class="cn.tj.domain.MyDatasource"
          init-method="init" destroy-method="destroy" scope="prototype"></bean>
</beans>

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

<?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">
    <!--set注入:注入emp1的关联对象-->
    <bean id="person1" class="cn.tj.domain.Person">
        <property name="name" value="叶凡"></property>
    </bean>
    <!--set注入:注入基本数据类型-->
    <bean id="emp1" class="cn.tj.domain.Employee">
        <property name="name" value="石昊"></property>
        <property name="age" value="20"></property>
        <property name="phone" value="1332253222"></property>
        <!--set注入:注入对象-->
        <!--<property name="对象属性名称" ref="容器另外一个 bean 的 id 值"/>-->
        <property name="person" ref="person1"></property>
    </bean>
    <bean id="emp2" class="cn.tj.domain.Employee">
        <property name="name" value="塔兹米"></property>
        <property name="age" value="17"></property>
        <property name="phone" value="1332568222"></property>
        <property name="person" ref="person1"></property>
    </bean>
</beans>

④ 测试

@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

	<!--dao创建-->
    <bean id="employeeDao" class="cn.tj.dao.EmployeeDaoImpl"></bean>
    <bean id="employeeDao2" class="cn.tj.dao.EmployeeDaoImpl2"></bean>
    <!--service 层 setter 注入 dao-->
    <bean id="employeeService" class="cn.tj.service.EmployServiceImpl">
        <property name="employeeDao" ref="employeeDao"></property>
    </bean>

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

 <!--
 构造注入
 name 实体类的属性名
 index 有参构造的参数索引值 从0开始
 type 参数的类型
 value 设置的属性值
 ref 关联引入的bean
 -->
 	<!--构造注入:需要设置的参数和有参构造的形参类型和数量对应-->
    <bean id="student1" class="cn.tj.domain.Student">
        <constructor-arg value="叶凡" name="name" ></constructor-arg>
        <constructor-arg name="sn" value="001"></constructor-arg>
        <constructor-arg name="phone" value="13504568169"></constructor-arg>
    </bean>
    <bean id="student2" class="cn.tj.domain.Student">
        <constructor-arg index="0" value="石昊" ></constructor-arg>
        <constructor-arg index="1" value="002"></constructor-arg>
        <constructor-arg index="2" value="13504568169"></constructor-arg>
    </bean>
    <bean id="student3" class="cn.tj.domain.Student">
        <constructor-arg type="java.lang.String" value="塔兹米" ></constructor-arg>
        <constructor-arg type="java.lang.Long" value="003"></constructor-arg>
        <constructor-arg type="java.lang.String" value="13504568169"></constructor-arg>
    </bean>
    <!--创建当前时间-->
    <bean id="date" class="java.util.Date"></bean>
    <bean id="student4" class="cn.tj.domain.Student">
        <constructor-arg type="java.lang.String" value="张起灵" ></constructor-arg>
        <constructor-arg type="java.lang.Long" value="003"></constructor-arg>
        <constructor-arg type="java.lang.String" value="13422222"></constructor-arg>
        <constructor-arg name="birthday" ref="date"></constructor-arg>
    </bean>

③ 测试方法

@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 + "]";
	}
}

配置文件

<bean id="student " class="cn.tj.domain.Dog"/>
<bean id="teacher" class="cn.tj.domain.Person"/>

测试类

@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();
	}
}

你可能感兴趣的:(#,Java研学,java,spring,开发语言)