文章目录
- 1、Spring 基于注解的配置
- 基于注解的配置
- 引入依赖包
- 配置
- 实体类
- 数据访问层
- 业务层
- 业务层实现
- 测试
- 2、@Bean和@Component和@Configuration的区别
- 1 @Bean:
- 2 @Component:
- 3 @Configuration:
- 总结:
- 区别
- @Component和@Configuration区别
- 3、Spring读取properties配置文件
- 准备配置文件
- 通过配置文件配置
- 方式一:
- 方式二:
- 使用
- 导入依赖包
- 测试
- 输出,表示连接上数据库
- 通过注解配置
- 在AppConfig中导入DatabaseConfig
- 测试
- 输出
- 4、Spring 中的监听器事件
- Spring 中的事件处理
- Spring 提供了以下的标准事件:
- 监听上下文事件
- 下面是 **CSRefreshedEventHandler.java** 文件的内容:
- 下面是 **CStartEventHandler.java** 文件的内容:
- 下面是 **CStopEventHandler.java** 文件的内容:
- 下面是 **CSClosedEventHandler.java** 文件的内容:
- 下面是 调用的内容:
- 输出以下消息:
- 5、Spring整合junit
- 整合Junit5
- 引入包
- 注解版
- 配置文件xml版
- 6、Spring SpEL表达式语言
- 一、${}
- 二、${}使用
- 总结
- 上一篇:[Spring (三) 之Aop及事务控制](https://blog.csdn.net/qq_45525848/article/details/137721166)
1、Spring 基于注解的配置
基于注解的配置
从 Spring 2.5 开始就可以使用注解来配置依赖注入。而不是采用 XML 来描述一个 bean 连线,你可以使用相关类,方法或字段声明的注解,将 bean 配置移动到组件类本身。
在 XML 注入之前进行注解注入,因此后者的配置将通过两种方式的属性连线被前者重写。
注解连线在默认情况下在 Spring 容器中不打开。因此,在可以使用基于注解的连线之前,我们将需要在我们的 Spring 配置文件中启用它。所以如果你想在 Spring 应用程序中使用的任何注解,可以考虑到下面的配置文件。
@Configuration的约束
Configuration类必须作为类提供(即不作为从工厂方法返回的实例),以允许通过生成的子类增强运行时
配置类必须不是final。
配置类必须是非本地的(即,不能在方法中声明)。
任何嵌套的配置类都必须声明为static。
@Bean 方法不会再创建其他配置类(任何此类实例都将被视为常规Bean,其配置注释不会被检测到)。
引入依赖包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.19</version>
</dependency>
配置
package com.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com")
public class AppConfig {
}
实体类
package com.entity;
import lombok.Data;
@Data
public class User {
private Long id;
private String userName;
private String password;
}
数据访问层
package com.dao;
import org.springframework.stereotype.Repository;
@Repository
public class UserDao {
public void save(){
System.out.println("save....");
}
}
业务层
package com.service;
public interface UserService {
void save();
}
业务层实现
package com.service.impl;
import com.dao.UserDao;
import com.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService {
@Autowired
UserDao userDao;
@Override
public void save() {
userDao.save();
}
}
测试
package com.main;
import com.config.AppConfig;
import com.service.UserService;
import com.service.impl.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class StartApplication {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = context.getBean(UserServiceImpl.class);
userService.save();
}
}
2、@Bean和@Component和@Configuration的区别
@Bean, @Component, 和 @Configuration 是Spring Framework中用于配置Bean的三个不同注解,它们有以下区别:
1 @Bean:
-
作用:@Bean注解用于在配置类中声明Bean对象。当你希望自己控制Bean的创建过程,并将其添加到Spring容器中时,可以使用@Bean注解。
-
使用方式:将@Bean注解放在一个方法上,并在该方法中实例化并返回一个Bean对象。Spring会将这个Bean注册到容器中,供其他组件使用。
2 @Component:
-
作用:@Component是通用的组件扫描注解,用于标记一个类为Spring管理的组件。通过组件扫描,Spring会自动将带有@Component注解的类注册为Bean,并将其添加到Spring容器中。
-
使用方式:将@Component注解放在一个类上,Spring会自动扫描并将这个类实例化并注册为Bean。
3 @Configuration:
-
作用:@Configuration注解表示一个类是配置类,用于声明Bean的创建和其他配置。配置类类似于XML配置文件,可以用来替代XML配置,用于定义Bean和其他组件。
-
使用方式:将@Configuration注解放在一个类上,通常会结合@Bean注解一起使用,在配置类中定义Bean的创建过程。
总结:
● @Bean主要用于配置类中手动定义Bean。
● @Component用于自动组件扫描注册Bean。
● @Configuration用于定义配置类,类似于XML配置文件,用于声明Bean和其他组件。
区别
@Bean的实例化和初始化操作由开发人员完成,bean的生命周期IOC不负责。
@Component/@Configuration实例化,初始化由容器来完成,bean的生命周期由IOC容器管理
@Component和@Configuration区别
用@Component修饰的类,在方法中相互调用的时候每次都会调用。而用@Configuration只调用一次。
// @Configuration
@Component
public class BeanConfig {
@Bean
public User user1() {
User user = new User();
System.out.println("BeanConfig.user1:" + user);
return user;
}
@Bean
public String testUser() {
// @Configuration 每次调用user1()返回的都是容器中的对象
// @Component 每次调用user1()都会创建一个新的对象
User user = user1();
System.out.println(user);
return "hello";
}
}
3、Spring读取properties配置文件
一般properties文件,用于在代码块中读取,并給变量赋值。但是,Spring可以Bean XML方式定义(注册Bean)中,可以通过${属性名}使用properties文件配置的值。或者在代码中使用@Value注解读取properties的属性值。
准备配置文件
在resources文件夹下创建jdbc.properties
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/company
jdbc.user=root
jdbc.pwd=root
所以用途有两种:
通过配置文件配置
Spinrg的Bean XML定义中,可以通过${属性名}使用properties文件配置的值
首先,必须先加载properties配置文件,方式有两种,如下
方式一:
<?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">
<!--
用途1:Spring的xml配置文件中,可以通过${属性名}使用properties文件配置的值
用途2:可以使用@Value("${属性名}")注解读取properties文件配置的值,再给字段赋值
方法1:注解在字段上,给字段赋值
方法2:注解在字段的setter方法中赋值
-->
<!-- 加载配置文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
</beans>
方式二:
<?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">
<!--
用途1:Spring的xml配置文件中,可以通过${属性名}使用properties文件配置的值
用途2:可以使用@Value("${属性名}")注解读取properties文件配置的值,再给字段赋值
方法1:注解在字段上,给字段赋值
方法2:注解在字段的setter方法中赋值
-->
<!-- 加载配置文件 -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="jdbc.properties" />
</bean>
</beans>
可以清楚的看到,方式一,非常地简洁,但是如果要使用多个properties就可能实现不了,其实可以通过通配符实现,会有点麻烦。
使用
接着,就可以在Bean的定义中,使用properties中的属性值,如下
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.user}" />
<property name="password" value="${jdbc.pwd}" />
</bean>
导入依赖包
这里只是方便测试,测试了连接数据库而已,非必须的!!
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.15</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
测试
ApplicationContext ctx = new ClassPathXmlApplicationContext("Bean.xml");
DataSource dataSource = ctx.getBean("dataSource", DriverManagerDataSource.class);
System.out.println(dataSource);
System.out.println(dataSource.getConnection());
输出,表示连接上数据库
org.springframework.jdbc.datasource.DriverManagerDataSource@144ab983
com.mysql.cj.jdbc.ConnectionImpl@67b61834
通过注解配置
@Configuration可以配合@PropertySource导入properties配置。
之后通过@Value,配合Spring的EL表达式,和JSP中的EL表达式有点类似,后面SpringEL表达式模块会遇到详细用法。
@Configuration
@PropertySource("classpath:jdbc.properties")
public class DatabaseConfig {
@Value("${jdbc.url}")
String url;
@Value("${jdbc.driver}")
String driver;
@Value("${jdbc.user}")
String user;
@Value("${jdbc.pwd}")
String pwd;
@Bean
public DataSource dataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl(url);
dataSource.setDriverClassName(driver);
dataSource.setUsername(user);
dataSource.setPassword(pwd);
return dataSource;
}
}
在AppConfig中导入DatabaseConfig
@Configuration
@ComponentScan("com")
@Import({DatabaseConfig.class})
public class AppConfig {
}
测试
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
DataSource dataSource = ctx.getBean(DataSource.class);
System.out.println(dataSource.getConnection());
输出
com.mysql.cj.jdbc.ConnectionImpl@5f08fe00
4、Spring 中的监听器事件
Spring 中的事件处理
你已经看到了在所有章节中 Spring 的核心是 ApplicationContext,它负责管理 beans 的完整生命周期。当加载 beans 时,ApplicationContext 发布某些类型的事件。例如,当上下文启动时,ContextStartedEvent 发布,当上下文停止时,ContextStoppedEvent 发布。
通过 ApplicationEvent 类和 ApplicationListener 接口来提供在 ApplicationContext 中处理事件。如果一个 bean 实现 ApplicationListener,那么每次 ApplicationEvent 被发布到 ApplicationContext 上,那个 bean 会被通知。
Spring 提供了以下的标准事件:
Spring 内置事件 & 描述 |
---|
ContextRefreshedEvent : ApplicationContext 被初始化或刷新时,该事件被发布。这也可以在 ConfigurableApplicationContext 接口中使用 refresh() 方法来发生。 |
ContextStartedEvent: 当使用 ConfigurableApplicationContext 接口中的 start() 方法启动 ApplicationContext 时,该事件被发布。你可以调查你的数据库,或者你可以在接受到这个事件后重启任何停止的应用程序。 |
ContextStoppedEvent: 当使用 ConfigurableApplicationContext 接口中的 stop() 方法停止 ApplicationContext 时,发布这个事件。你可以在接受到这个事件后做必要的清理的工作。 |
ContextClosedEvent: 当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。一个已关闭的上下文到达生命周期末端;它不能被刷新或重启。 |
RequestHandledEvent: 这是一个 web-specific 事件,告诉所有 bean HTTP 请求已经被服务。 |
由于 Spring 的事件处理是单线程的,所以如果一个事件被发布,直至并且除非所有的接收者得到的该消息,该进程被阻塞并且流程将不会继续。因此,如果事件处理被使用,在设计应用程序时应注意。
监听上下文事件
为了监听上下文事件,一个 bean 应该实现只有一个方法 onApplicationEvent() 的 ApplicationListener 接口。因此,我们写一个例子来看看事件是如何传播的,以及如何可以用代码来执行基于某些事件所需的任务。
下面是 CSRefreshedEventHandler.java 文件的内容:
@Component
public class CSRefreshedEventHandler implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
System.out.println("ContextRefreshedEvent Received");
}
}
下面是 CStartEventHandler.java 文件的内容:
@Component
public class CStartEventHandler implements ApplicationListener<ContextStartedEvent>{
public void onApplicationEvent(ContextStartedEvent event) {
System.out.println("ContextStartedEvent Received");
}
}
下面是 CStopEventHandler.java 文件的内容:
@Component
public class CStopEventHandler implements ApplicationListener<ContextStoppedEvent>{
public void onApplicationEvent(ContextStoppedEvent event) {
System.out.println("ContextStoppedEvent Received");
}
}
下面是 CSClosedEventHandler.java 文件的内容:
@Component
public class CSClosedEventHandler implements ApplicationListener<ContextClosedEvent> {
@Override
public void onApplicationEvent(ContextClosedEvent event) {
System.out.println("ContextClosedEvent Received");
}
}
下面是 调用的内容:
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
ctx.start();
ctx.stop();
ctx.close();
输出以下消息:
ContextRefreshedEvent Received
ContextStartedEvent Received
ContextStoppedEvent Received
ContextClosedEvent Received
5、Spring整合junit
整合Junit5
引入包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.19</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.8.2</version>
<scope>test</scope>
</dependency>
注解版
上面的其他代码不变,修改测试代码模块
@SpringJUnitConfig(classes = {AppConfig.class})
public class MyTestSpringJunit4 {
@Autowired
HelloWorld helloWorld;
@Test
public void testA(){
System.out.println(helloWorld);
}
}
配置文件xml版
@SpringJUnitConfig(locations = "classpath:Beans.xml")
public class JunitSpringXmlTest {
}
6、Spring SpEL表达式语言
一、${}
${} 用于加载外部文件指定的Key值,常用在xml和注解中,@Value(" ${key_value}")
二、${}使用
在resources文件夹下面创建创建jdbc.properties文件
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/company
jdbc.user=root
jdbc.pwd=root
package com.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource("classpath:jdbc.properties")
public class AppConfig {
@Value("${jdbc.url}")
String url;
@Value("${jdbc.user}")
String username;
@Value("${jdbc.pwd}")
String password;
@Value("${jdbc.driver}")
String driverClassName;
public void print(){
System.out.println("url = " + url);
System.out.println("username = " + username);
System.out.println("password = " + password);
System.out.println("driverClassName = " + driverClassName);
}
}
package com;
import com.config.AppConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
AppConfig appConfig = ctx.getBean(AppConfig.class);
appConfig.print();
}
}
打印结果
url = jdbc:mysql://localhost:3306/company
username = root
password = root
driverClassName = com.mysql.cj.jdbc.Driver
总结
${}用的比较多,主要是用来获取配置文件的数据,比如获取数据库连接信息。