目录
2.4.3 其他Bean对象获取properties⽂件内容
1 Spring框架发展史
1.1 Spring1.x时代
在 Spring1.x 时代,都是通过 xml ⽂件配置 bean,随着项⽬的不断扩⼤,需要将 xml 配置分放到不 同的配置⽂件中,需要频繁的在 java 类和 xml 配置⽂件中切换。
1.2 Spring2.x时代
随着 JDK 1.5 带来的注解⽀持,Spring2.x 可以使⽤注解对Bean进⾏声明和注⼊,⼤⼤的减少了 xml 配置⽂件,同时也⼤⼤简化了项⽬的开发。 那么,问题来了,究竟是应该使⽤ xml 还是注解呢?
最佳实践: 1. 应⽤的基本配置⽤ xml,⽐如:数据源、资源⽂件等;
2. 业务开发⽤注解,⽐如:Service 中注⼊ bean 等;
1.3 Spring3.x到4.x再到Spring5.x
从 Spring3.x 开始提供了 Java 配置⽅式,使⽤ Java 配置⽅式可以更好的理解你配置的 Bean,现在我 们就处于这个时代,并且 Spring4.x、Spring5.x 和 Spring Boot 都推荐使⽤ java 配置的⽅式。
2 Spring 5.x应用零配置开发
Spring 框架从 5.x 版本推荐使⽤注解形式来对 java 应⽤程序进⾏开发与配置,并且可以完全替代原 始的 XML + 注解形式的开发,在使⽤注解形式进⾏项⽬开发与环境配置时,Spring 框架提供了针对环 境配置与业务 bean 开发相关注解。
2.1 注解
2.1.1 声明Bean注解
@Component: 组件 没有明确规定其⻆⾊,作⽤在类级别上声明当前类为⼀个业务组件,被Spring Ioc 容器维护
@Service: 在业务逻辑层(Service 层)类级别进⾏声明
@Repository: 在数据访问层(dao 层) 类级别声明
@Controller: 在展现层(MVC) 使⽤ 标注当前类为⼀个控制器
2.1.2 注入Bean注解
@AutoWired: Spring 官⽅提供注解
@Inject: JSR-330 提供注解(标准制定⽅)
@Resource: JSR-250 提供注解
2.1.3 Spring5.x 中配置与获取Bean注解
@Configuration: 作⽤与类上,将当前类声明为⼀个配置类,相当于⼀个xml 配置⽂件
@ComponentScan: ⾃动扫描指定包下标注有@Repository,@Service,@Controller
@Component: 注解的类并由Ioc 容器进⾏实例化和维护
@Bean: 作⽤于⽅法上,相当于xml ⽂件中 声明当前⽅法返回值为⼀个bean
@Value: 获取properties ⽂件指定key value值
2.2 实例1 - IOC 中 Bean 的实例化与获取
2.2.1 创建 Spring 普通⼯程
在 pom.xml 中添加坐标相关配置:
<dependencies>
<!-- spring的依赖坐标 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.4.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 指定Maven编译的JDK版本和编码 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<!-- 源代码使⽤的JDK版本 -->
<source>1.8</source>
<!-- 需要⽣成的⽬标class⽂件的编译版本 -->
<target>1.8</target>
<!-- 字符集编码 -->
<encoding>utf-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
2.2.2 创建Bean对象
UserDao.java:
@Repository
public class UserDao {
public void test(){
System.out.println("UserDao.test...");
}
}
UserService.java:
@Service
public class UserService {
@Resource
private UserDao userDao;
public void test(){
System.out.println("UserService.test...");
userDao.test();
}
}
2.2.3 创建 IocConfig 配置类
// 将当前类声明为⼀个配置类
@Configuration
// 设置扫描包范围
@ComponentScan("com.xxxx.springboot")
public class IocConfig {
}
2.2.4 创建启动类执⾏测试
public class Starter {
public static void main(String[] args) {
// 基于Java的配置类加载Spring的应⽤上下⽂
AnnotationConfigApplicationContext ac = new
AnnotationConfigApplicationContext(IocConfig.class);
// 获取指定的Bean对象
UserService userService = ac.getBean(UserService.class);
// 调⽤Bean对象的⽅法
userService.test();
}
}
此时启动 Spring IOC 容器,通过实例化 AnnotationConfigApplicationContext 类,接收配置参 数类IocConfig,并获取 UserService Bean 实现⽅法调⽤,此时应⽤环境不存在 xml 配置⽂件,简化了 应⽤的 xml 配置。
2.3 实例2 - @Bean注解使⽤
使⽤@Bean 注解声明在⽅法(注意:⽅法名⼀般为bean对象名称)级别⽤于返回实例化的Bean对 象。
2.3.1 创建Bean对象
AccountDao.java:
// 注意:此时类级别并未添加 @Repository 注解
public class AccountDao {
public void test(){
System.out.println("AccountDao.test...");
}
}
2.3.2 修改 IocConfig 配置类
添加返回AccountDao Bean对象⽅法:
@Configuration
@ComponentScan("com.xxxx.springboot")
public class IocConfig02 {
// 返回实例化的单例Bean对象
@Bean
public AccountDao accountDao(){
return new AccountDao();
}
}
2.3.3 创建启动类并执⾏测试
public class Starter02 {
public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new
AnnotationConfigApplicationContext(IocConfig.class);
// 判断IocConfig对象是否是单例
System.out.println(ac.isSingleton("IocConfig"));
// 获取IocConfig对象
IocConfig iocConfig = ac.getBean(IocConfig.class);
// 获取AccountDao对象
AccountDao accountDao01 = iocConfig.accountDao();
AccountDao accountDao02 = iocConfig.accountDao();
System.out.println(accountDao01 + "," + accountDao02);
accountDao01.test();
}
}
2.4 实例3 - 读取外部配置⽂件
在开发 Java web 应⽤时,配置⽂件是⽐较常⻅的,⽐如 xml,properties,yml 等⽂件,在 Spring 应⽤中对于配置⽂件的读取同样提供⽀持。对于配置⽂件读取,我们可以通过 @PropertySource 注解声明到类级别来指定读取相关配置。
Spring El 表达式语⾔,⽀持在 Xml 和注解中使⽤表达式,类似于 JSP 中 EL 表达式,Spring 框架借 助该表达式实现资源注⼊,主要通过 @Value 注解来使⽤表达式,通过 @Value 注解,可以实现普通字 符串,表达式运算结果,Bean 属性⽂件内容,属性⽂件等参数注⼊。具体使⽤如下:
2.4.1 准备配置文件
src/main/resources ⽬录下添加 user.properties、jdbc.properties ⽂件:
# user.properties
user.userName=admin
user.password=admin
# jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/hr?useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=root
2.4.2 @PropertySource 加载配置⽂件
通过 @PropertySource 加载 properties 配置⽂件:
@Configuration
@ComponentScan("com.xxxx")
@PropertySource(value =
{"classpath:jdbc.properties","classpath:user.properties"})
public class IocConfig03 {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String userName;
@Value("${jdbc.password}")
private String password;
// 控制台打印属性值信息
public void showConfigInfo(){
System.out.println("driver:" + driver + ",url:" + url);
System.out.println("userName:" + userName + ",password:" + password);
}
}
2.4.3 其他Bean对象获取properties⽂件内容
@Service
public class UserService {
@Resource
private UserDao userDao;
@Value("${user.userName}")
private String userName;
@Value("${user.password}")
private String password;
public void test(){
System.out.println("UserService.test...");
userDao.test();
System.out.println("userName:" + userName + ",password:" + password);
}
}
启动,查看控制台输出内容效果
2.5 组合注解与元注解
Spring 从2.x版本开始引⼊注解⽀持(⽬的是jdk1.5中推出注解功能),通过引⼊注解来消除⼤量xml 配 置,Spring 引⼊注解主要⽤来注⼊ bean 以及 aop 切⾯相关配置,但由于注解⼤量使⽤,就会造成⼤ 量重复注解代码出现,代码出现了重复,Spring 为了消除重复注解,在元注解上引⼊了组合注解,其实 可以理解为对代码的重构,相当于注解的注解,拥有元注解的原始功能,⽐如在定义配置类时⽤到的 @Configuration 注解就是组合注解,拥有 @Component 注解功能,即配置类本身也是⼀个被 IOC 维 护的单例 Bean。
2.5.1 自定义组合注解
定义 MyCompScan 注解,拥有 @ComponentScan 扫描器注解功能:
/**
* 组合注解MyCompScan 定义
* 拥有元注解@Configuration + @ComponentScan 两者功能
* 覆盖 value 属性
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Configuration
@ComponentScan
public @interface MyCompScan {
String[] value() default {};
}
2.5.2 应用组合注解
@MyCompScan("com.xxxx.springboot")
@PropertySource(value =
{"classpath:jdbc.properties","classpath:user.properties"})
public class IocConfig04 {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String userName;
@Value("${jdbc.password}")
private String password;
public void showConfigInfo(){
System.out.println("driver:" + driver + ",url:" + url);
System.out.println("userName:" + userName + ",password:" + password);
}
}
测试组合注解:
public class Starter {
public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new
AnnotationConfigApplicationContext(IocConfig04.class);
UserService userService = ac.getBean(UserService.class);
userService.test();
}
}