【笔记】SpringFramework注解开发

前言

SpringFramework注解开发学习笔记
Spring2.5开始出现注解开发方式
Spring3.0开始改为纯注解开发方式

注解开发替换Spring核心配置文件

  • 相当于将如下配置改为了注解方式开发
src/main/resources/applicationContext.xml
1
2
3
4
5
6
7
<?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">

</beans>

添加配置类

  • 在类上添加@Configuration注解,表示定义一个Spring配置
src/main/resources/applicationContext.xml
1
2
3
4
5
6
7
package com.conf;

import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringConfig {
}

注解开发替换bean配置

  • 相当于将如下配置改为了注解方式开发
src/main/resources/applicationContext.xml
1
<bean />

添加包扫描

  • 创建Spring配置文件,并修改<beans></beans>中的属性,开启context命名空间

<context:component-scan/>
base-package="":指定被扫描的包,包内及其子包内的所有类都会被扫描

src/main/resources/applicationContext.xml
1
2
3
4
5
6
7
8
9
10
11
12
<?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">

<context:component-scan base-package="com"/>

</beans>

配置bean

  • 在类上添加@Component注解,表示定义一个bean
src/main/java/com/service/UserService.java
1
2
3
4
5
6
7
package com.service;

import org.springframework.stereotype.Component;

@Component
public class UserService {
}

定义一个有id的bean

@Component(""):指定bean的id

src/main/java/com/service/UserService.java
1
2
3
4
5
6
7
package com.service;

import org.springframework.stereotype.Component;

@Component("")
public class UserService {
}

定义特殊的bean

  • 为不同用途的类定义不同的注解,用于区分不同用途的bean,其本质与@Component没有任何区别
表现层的bean
1
2
3
4
5
6
7
package com.controller;

import org.springframework.stereotype.Controller;

@Controller
public class UserController {
}
业务层的bean
1
2
3
4
5
6
7
package com.service;

import org.springframework.stereotype.Service;

@Service
public class UserService {
}
数据层的bean
1
2
3
4
5
6
7
package com.dao;

import org.springframework.stereotype.Repository;

@Repository
public class UserDao {
}

注解开发替换包扫描配置

  • 相当于将如下配置改为了注解方式开发
src/main/resources/applicationContext.xml
1
<context:component-scan base-package="com"/>

添加配置类

  • 在类上添加@ComponentScan(""),表示添加包扫描配置
src/main/resources/applicationContext.xml
1
2
3
4
5
6
7
package com.conf;

import org.springframework.context.annotation.ComponentScan;

@ComponentScan("com")
public class SpringConfig {
}

指定多个包扫描配置

src/main/resources/applicationContext.xml
1
2
3
4
5
6
7
package com.conf;

import org.springframework.context.annotation.ComponentScan;

@ComponentScan({"com.controller", "com.service", "com.dao"})
public class SpringConfig {
}

注解开发时使用配置类获取IoC容器

SpringConfig.class:指定配置类

src/main/java/com/Application.java
1
2
3
4
5
6
7
public class Application {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
UserService obj = (UserService) applicationContext.getBean("userService");
obj.method();
}
}

注解开发替换单例配置

  • 在类上添加@Scope注解

@Scope(""):配置bean是否为单例

singleton:单例
prototype:非单例

src/main/java/com/service/UserService.java
1
2
3
4
5
6
7
8
package com.service;

import org.springframework.stereotype.Component;

@Component
@Scope("")
public class UserService {
}

注解开发替换生命周期方法配置

  • 在方法上添加@PostConstruct注解,表示初始化方法,在构造方法执行之后执行
  • 在方法上添加@PreDestroy注解,表示销毁方法,在彻底销毁之前执行
src/main/java/com/service/UserService.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.service;

import org.springframework.stereotype.Component;

@Component
public class UserService {

@PostConstruct
public void init() {
}

@PreDestroy
public void destroy() {
}

}

注解开发替换自动装配配置

  • 底层使用暴力反射为属性赋值,所以无需setter方法
  • 自动装配默认使用无参构造方法创建对象

引用类型

按照类型自动装配

  • 在需要注入引用类型的值的属性上添加@Autowired注解,默认将按照类型自动装配
src/main/java/com/service/UserService.java
1
2
3
4
5
6
7
8
9
package com.service;

import org.springframework.stereotype.Component;

@Component
public class UserService {
@Autowired
UserDao userDao;
}

按照名称自动装配

  • 在注入时优先按类型自动装配,当按出现相同类型出现多个时,自动改为按名称自动装配,此时自动装配的名称依据是由变量名决定的
  • 如果需要手动指定自动装配的名称依据,可以使用@Qualifier("")注解指定自动装配的名称依据
src/main/java/com/service/UserService.java
1
2
3
4
5
6
7
8
9
10
package com.service;

import org.springframework.stereotype.Component;

@Component
public class UserService {
@Autowired
@Qualifier("")
UserDao userDao;
}

基本类型(值类型)

直接传值

  • 在需要注入基本类型的值的属性上添加@Value("")注解
src/main/java/com/service/UserService.java
1
2
3
4
5
6
7
8
9
package com.service;

import org.springframework.stereotype.Component;

@Component
public class UserService {
@Value("")
String str;
}

传递properties文件的值

在配置类引入properties文件
  • 在配置类上添加@PropertySource("")注解来引入properties文件
  • 不可以使用通配符

@PropertySource("xxx.properties"):引入单个properties文件

@PropertySource("classpath:xxx.properties"):引入单个properties文件

@PropertySource({"xxx.properties", "xxx.properties"}):引入多个properties文件

src/main/java/com/conf/SpringConfig.java
1
2
3
4
5
6
7
8
package com.conf;

import org.springframework.context.annotation.Configuration;

@Configuration
@PropertySource("xxx.properties")
public class SpringConfig {
}
获取properties文件中的值
  • 通过@Value("${}")注解获取properties文件中的值

<key>:键。通过键,获取值

src/main/java/com/service/UserService.java
1
2
3
4
5
6
7
8
9
package com.service;

import org.springframework.stereotype.Component;

@Component
public class UserService {
@Value("${<key>}")
String str;
}

注解开发管理第三方bean

  • 以Druid为例

添加依赖

pom.xml
1
2
3
4
5
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>

通过方法返回值定义bean对象

  • 手动编程导入第三方bean

@Bean:定义方法的返回值为一个bean

src/main/java/com/conf/JDBCConfig.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.conf;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;

import javax.sql.DataSource;

public class JDBCConfig {

@Bean("dataSource")
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("");
dataSource.setUrl("");
dataSource.setUsername("");
dataSource.setPassword("");
return dataSource;
}
}

基本类型参数注入

  • 直接通过@Value():注入基本类型数据
src/main/java/com/conf/JDBCConfig.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.conf;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;

import javax.sql.DataSource;

public class JDBCConfig {

@Value("")
private String driver;
@Value("")
private String url;
@Value("")
private String username;
@Value("")
private String password;

@Bean("dataSource")
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driver);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
}

引用类型参数注入

  • 如果一个方法上有@bean注解,Spring会将这个方法的形参列表中的参数通过类型自动注入,所以只需要传递已经被Spring容器管理的bean类型的参数即可
在主配置类上包扫描
src/main/java/com/conf/SpringConfig.java
1
2
3
4
5
6
7
8
9
10
11
package com.conf;

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

@Configuration
@Import(JDBCConfig.class)
@ComponentScan("com")
public class SpringConfig {
}
将其他类交由Spring容器管理
src/main/java/com/dao/UserDao.java
1
2
3
4
5
6
7
package com.dao;

import org.springframework.stereotype.Repository;

@Repository
public class UserDao {
}
引用类型参数注入
src/main/java/com/conf/JDBCConfig.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.conf;

import com.alibaba.druid.pool.DruidDataSource;
import com.dao.UserDao;
import org.springframework.context.annotation.Bean;

import javax.sql.DataSource;

public class JDBCConfig {

@Bean("dataSource")
public DataSource dataSource(UserDao userDao) {
System.out.println(userDao);

DruidDataSource dataSource = new DruidDataSource();
return dataSource;
}
}

在主配置类上导入其他配置类

@Import(JDBCConfig.class):导入其他类
@Import({JDBCConfig.class, JDBCConfig.class}):导入多个其他类

src/main/java/com/conf/SpringConfig.java
1
2
3
4
5
6
7
8
9
package com.conf;

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

@Configuration
@Import(JDBCConfig.class)
public class SpringConfig {
}

获取并使用bean对象

  • 注解开发时,使用主配置类获取IoC容器
src/main/java/com/Application.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com;

import com.conf.SpringConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import javax.sql.DataSource;

public class Application {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
DataSource dataSource = applicationContext.getBean(DataSource.class);
System.out.println(dataSource);
}
}

完成

参考文献

哔哩哔哩——黑马程序员