Spring基础知识学习总结(四)

(5)Spring新注解

使用上面的注解还不能全部替代xml配置文件,还需要使用注解替代的配置如下:

  • 非自定义的Bean的配置:<bean>
  • 加载properties文件的配置:<context:property-placeholder>
  • 组件扫描的配置:<context:component-scan>
  • 引入其他文件:<import>

即创建配置类,替代xml配置文件

@Configuration //用于指定当前类是一个 Spring 配置类,当创建容器时会从该类上加载注解
@ComponentScan
//用于指定 Spring 在初始化容器时要扫描的包。
//作用和在 Spring 的 xml 配置文件中的context:component-scan base-package="com"/>一样
@Bean //使用在方法上,标注将该方法的返回值存储到 Spring 容器中
@PropertySource //用于加载.properties 文件中的配置
@Import //用于导入其他配置类

 (6) 完全注解开发测试

原始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:context="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
       http://www.springframework.org/schema/context/spring-context.xsd
">
<!--    <bean id="accountDao" class="com.hhh.Dao.Impl.AccountDaoImpl"></bean>-->

<!--    <bean id="accountService" class="com.hhh.Service.Impl.AccountServiceImpl">-->
<!--        <property name="accountDao" ref="accountDao"/>-->
<!--    </bean>-->

<!--    组件扫描:Spring容器会扫描这个包里所有类,从类的注解信息中获取Bean的信息-->
    <context:component-scan base-package="com.hhh"></context:component-scan>

<!--    加载外部的properties文件-->
    <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="root"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
</beans>

 

1> 新建一个核心配置类:SpringConfiguration,相当于总配置

package com.hhh.common;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
//声明当前类是一个配置类
@ComponentScan("com.hhh")
//开启包扫描 相当于xml中的<context:component-scan base-package="com.hhh"/>
@Import({DataSourceConfiguration.class})
//导入其他配置类
//@Import({DataSourceConfiguration.class}) 里面的值其实是一个数组,可以加载多个类,如:@Import({DataSourceConfiguration1.class,DataSourceConfiguration2.class})
public class SpringConfiguration {
}

2> 新建数据源配置类:DataSourceConfiguration,相当于分配置

package com.hhh.common;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;

@PropertySource("classpath:jdbc.properties")
//加载外部配置文件相当于<context:property-placeholder location="classpath:jdbc.properties"/>
public class DataSourceConfiguration {
    @Value("${jdbc.driver}")
    private String driver;

    @Value("${jdbc.url}")
    private String url;

    @Value("${jdbc.username}")
    private String username;

    @Value("${jdbc.password}")
    private String password;

    @Bean("dataSource") //Spring会将当前方法的返回值以指定名称存到Spring容器当中
    public DataSource getDataSource() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass(driver);
        dataSource.setJdbcUrl(url);
        dataSource.setUser(username);
        dataSource.setPassword(password);
        return dataSource;
    }
}

3> 测试加载核心配置类创建Spring容器

package com.hhh.Controller;

import com.hhh.Service.AccountService;
import com.hhh.common.SpringConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class AccountController {
    public static void main(String[] args) {
//        ApplicationContext app = new ClassPathXmlApplicationContext("note.xml");
//        ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("note.xml");
        ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfiguration.class);
        AccountService accountService = app.getBean(AccountService.class);
        accountService.save();
//        app.close();
    }
}

4> 测试结果

 

 

最终pom文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.example</groupId>
  <artifactId>spring_temp</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>6.0.13</version>
    </dependency>

    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.33</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
        <version>6.0.13</version>
    </dependency>
    <dependency>
      <groupId>javax.annotation</groupId>
      <artifactId>javax.annotation-api</artifactId>
      <version>1.3.2</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
    <dependency>
      <groupId>com.mchange</groupId>
      <artifactId>c3p0</artifactId>
      <version>0.9.5.2</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>6.0.13</version>
    </dependency>

    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.30</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.2</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.assertj</groupId>
      <artifactId>assertj-core</artifactId>
      <version>3.24.2</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

c. bean的生命周期

1.  定义

对于普通的 Java 对象,当 new 的时候创建对象,然后该对象就能够使用了。一旦该对象不再被使用,则由 Java 自动进行垃圾回收。

而 Spring 中的对象是 bean,bean 和普通的 Java 对象没啥大的区别,只不过 Spring 不再自己去 new 对象了,而是由 IoC 容器去帮助我们实例化对象并且管理它,我们需要哪个对象,去问 IoC 容器要即可。IoC 其实就是解决对象之间的耦合问题,Spring Bean 的生命周期完全由容器控制。

2. 周期过程 

(1)通过构造器创建 bean 实例(无参数构造)
(2)为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
(3)把 bean 实例传递 bean 后置处理器的方法 postProcessBeforeInitialization
(4)调用 bean 的初始化的方法(需要进行配置初始化的方法)
(5)把 bean 实例传递 bean 后置处理器的方法 postProcessAfterInitialization
(6)bean 可以使用了(对象获取到了)
(7)当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)

 

 

以下是对您提出的问题的详细深入讲解:

(1)通过构造器创建bean实例(无参数构造)

在Spring中,通过无参数构造器创建bean实例是最常见的方式之一。当Spring容器启动时,它会查找指定类的无参数构造器,并使用反射机制来创建bean的实例。这种方式要求bean的类必须有一个可访问的无参数构造器。

配置方式

在Spring的XML配置文件中,通过<bean>标签的class属性指定bean的全限定类名(包名+类名),Spring会自动查找并使用该类的无参数构造器来创建bean实例。

<bean id="myBean" class="com.example.MyBeanClass"/>

(2)为bean的属性设置值和对其他bean引用(调用set方法)

Spring支持通过setter方法为bean的属性设置值,并且可以引用容器中的其他bean。这通过<property>标签在<bean>标签内部进行配置。

配置方式

  1. 设置基本类型和String类型的属性值

    <bean id="myBean" class="com.example.MyBeanClass">
    <property name="propertyName" value="propertyValue"/>
    </bean>
  2. 引用其他bean

    <bean id="anotherBean" class="com.example.AnotherBeanClass"/>
    <bean id="myBean" class="com.example.MyBeanClass">
    <property name="anotherBean" ref="anotherBean"/>
    </bean>

这里,MyBeanClass类中需要有setPropertyNamesetAnotherBean这两个setter方法。

(3)把bean实例传递bean后置处理器的方法postProcessBeforeInitialization

Bean后置处理器(BeanPostProcessor)是Spring框架中一种特殊的bean,用于在bean的初始化前后进行额外的处理。postProcessBeforeInitialization方法在bean的初始化方法(如配置的init-method)被调用之前执行。

配置方式

  1. 实现BeanPostProcessor接口

    public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    // 对bean进行自定义处理
    return bean; // 必须返回bean实例,以便继续后续的初始化流程
    }
    }
  2. 将BeanPostProcessor注册到Spring容器中

    <bean class="com.example.MyBeanPostProcessor"/>

(4)调用bean的初始化的方法(需要进行配置初始化的方法)

Spring允许通过配置文件指定bean的初始化方法,该方法会在bean的所有属性被设置之后调用。

配置方式

<bean>标签中使用init-method属性指定初始化方法。

<bean id="myBean" class="com.example.MyBeanClass" init-method="initMethod"/>

这里,MyBeanClass类中需要有initMethod这个无参数方法。

(5)把bean实例传递bean后置处理器的方法postProcessAfterInitialization

postProcessAfterInitialization方法在bean的初始化方法(如配置的init-method)被调用之后执行。它同样是在BeanPostProcessor接口中定义的。

执行时机

该方法的执行时机紧跟在bean的初始化方法之后,允许在bean完全初始化之后进行额外的处理。

(6)bean可以使用了(对象获取到了)

在Spring容器完成bean的创建、属性设置、初始化等流程后,bean就处于可用状态,可以通过ApplicationContextgetBean方法获取bean的实例。

获取方式

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
MyBeanClass myBean = context.getBean("myBean", MyBeanClass.class);

(7)当容器关闭时候,调用bean的销毁的方法(需要进行配置销毁的方法)

Spring允许通过配置文件指定bean的销毁方法,该方法会在容器关闭时被调用,用于执行清理工作。

配置方式

<bean>标签中使用destroy-method属性指定销毁方法。

<bean id="myBean" class="com.example.MyBeanClass" destroy-method="destroyMethod"/>

这里,MyBeanClass类中需要有destroyMethod这个无参数方法。

ps: bean生命周期的图引用了Spring Bean的生命周期(一图流+详细说明)_spring bean 生命周期图-CSDN博客

                                                       ❤️❤️❤️IOC完结撒花❤️❤️❤️

  • 23
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晚睡早起₍˄·͈༝·͈˄*₎◞ ̑̑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值