目录
一、完全注解开发理解
二、配置类和扫描注解
三、@Bean定义组件
四、@Bean注解细节
五、@import 扩展
一、完全注解开发理解
Spring 完全注解配置(Fully Annotation-based Configuration)是指通过 Java配置类 代码来配置 Spring 应用程序,使用注解来替代原本在 XML 配置文件中的配置。相对于 XML 配置,完全注解配置具有更强的类型安全性和更好的可读性。
由于前面的配置Bean的方式都设计到了XML的格式,所以就需要通过一种注解能实现完全实现抛开XML配置(因为XML文件配置读取的效率低)
二、配置类和扫描注解
注解 (Annotation) | 描述 (Description) |
---|---|
@Configuration | 用于标记一个类作为配置类。配置类用来定义Spring Bean以及配置其他组件。通常与@Bean注解一起使用,在配置类中声明方法来创建和配置Bean。 |
@PropertySource | 将外部属性文件加载到Spring环境中。通过该注解,可以将属性文件中定义的键值对作为Spring Bean的属性值来使用。 |
@ComponentScan | 指定要扫描的基础包。自动扫描基础包及其子包下的所有类,并将其注册为Spring Bean。可以设置过滤器来限制扫描范围,只扫描带有特定注解的类。 |
使用方法:
1.原来的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">
<!-- 扫描包-->
<context:component-scan base-package="com.alphamilk"/>
<!-- 导入资源文件-->
<context:property-placeholder location="Jdbc.properties"/>
</beans>
2.对应转换为完全注解方式
package com.alphamilk;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
//表明该类为注解类
@Configuration
//配置外部资源文件,相当于 <context:property-placeholder location="Jdbc.properties"/>
@PropertySource(value = "classpath:Jdbc.properties")
//声明扫描包 相当于<context:component-scan base-package="com.alphamilk"/>
@ComponentScan(value = "com.alphamilk")
public class Javaconfig {
}
两种通过注解创建ioc容器的方式(AnnotationConfigApplicationContext)
1.直接创建Annotation
public void test(){
// 1.创建ioc容器,并且导入对应的配置类
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Javaconfig.class);
// 2.获取组件
StudentController studentController = (StudentController) applicationContext.getBean("StudentController");
// 3.使用组件
studentController.getInfo();
}
2.通过创建实现类AnnotationConfigApplicationContext并调用regist方法
public void test(){
// 1.创建 ioc 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 2.设置配置类路径
applicationContext.register(Javaconfig.class);
// 3.获取Bean
StudentController bean = applicationContext.getBean(StudentController.class);
// 4.使用Bean
bean.getInfo();
}
总结:
@Configuration指定一个类为配置类,可以添加配置注解,替代配置xml文件
@ComponentScan(basePackages = {"包","包"}) 替代<context:component-scan标签实现注解扫描
@PropertySource("classpath:配置文件地址") 替代 <context:property-placeholder标签
配合IoC/DI注解,可以进行完整注解开发!
三、@Bean定义组件
场景需求:将Druid连接池对象存储到IoC容器
需求分析:第三方jar包的类,添加到ioc容器,无法使用@Component等相关注解!因为源码jar包内容为只读模式!
所以在注解类中只能通过传统的xml <bean 进行配置。但是通过@Bean注解就能解决
语法 | 描述 |
---|---|
@Bean | 表示该方法产生一个由 Spring 管理的 Bean。 |
@Bean(name="beanName") | 指定 Bean 的名称。 |
@Bean(initMethod="init") | 指定 Bean 的自定义初始化方法。 |
@Bean(destroyMethod="destroy") | 指定 Bean 的自定义销毁方法。 |
@Bean(autowire=Autowire.BY_NAME) | 指定 Bean 的自动装配模式为按名称自动装配。 |
@Bean(autowire=Autowire.BY_TYPE) | 指定 Bean 的自动装配模式为按类型自动装配。 |
@Bean(autowire=Autowire.NO) | 指定 Bean 不进行自动装配。 |
@Bean(autowire=Autowire.BY_NAME, initMethod="init") | 同时指定自动装配模式和初始化方法。 |
案例代码:
package com.alphamilk;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
//表明该类为注解类
@Configuration
//配置外部资源文件,相当于 <context:property-placeholder location="Jdbc.properties"/>
@PropertySource(value = "classpath:Jdbc.properties")
//声明扫描包 相当于<context:component-scan base-package="com.alphamilk"/>
@ComponentScan(value = "com.alphamilk")
public class Javaconfig {
@Value("${alphamilk.url}")
private String url;
@Value("${alphamilk.driver}")
private String Driver;
@Value("${alphamilk.username}")
private String username;
@Value("${alphamilk.password}")
private String password;
/*
<bean ->方法
方法的返回值类型 == bean组件的类型或者其他接口和父类
方法的名字 = bean id
方法体可以自定义实现过程
最重要的一步:通过加上@Bean 才会让配置类创建的组件存储到ioc容器中
*/
@Bean
public DruidDataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl(url);
dataSource.setDriverClassName(Driver);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
}
四、@Bean注解细节
1.关于BeanName的问题
1.1正常情况下Bean的Name默认为方法名字
// 正常情况下Bean的名字就是以下方法的dataSource
@Bean
public DruidDataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl(url);
dataSource.setDriverClassName(Driver);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
1.2通过@Bean name/value指定Name
// 通过@Bean(指定对应名字) hehhehehe
@Bean("hehhehehe")
public DruidDataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl(url);
dataSource.setDriverClassName(Driver);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
2.通过Bean指定对应的周期方法
2.1还是正常的Bean注解方式(@PostContruct 、 @PreDestory)
public class StudentController {
@PostConstruct
public void init(){
System.out.println("组件初始化");
}
@Autowired
StudentService service;
public void getInfo(){
System.out.println(service.getInfo());
}
@PreDestroy
public void destory(){
System.out.println("组件被销毁");
}
}
2.2可以通过调用@Bean内部的方法进行初始化与销毁
// 调用@Bean内部的方法进行初始化与销毁
@Bean(value = "dataSource",initMethod = "" ,destroyMethod = "")
public DruidDataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl(url);
dataSource.setDriverClassName(Driver);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
3.Bean的指定作用域
3.1Bean的指定作用域还是跟原来一样通过注解@Scope标签
// 通过@Scope注解实现,Bean的作用域
@Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Bean(value = "dataSource")
public DruidDataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl(url);
dataSource.setDriverClassName(Driver);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
4.Bean组件之间的调用
4.1方案1:直接调用对方的Bean方法即可
@Bean(value = "dataSource")
public DruidDataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl(url);
dataSource.setDriverClassName(Driver);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
public JdbcTemplate jdbcTemplate(){
JdbcTemplate jdbcTemplate = new JdbcTemplate();
// 传入对方的方法
jdbcTemplate.setDataSource(dataSource());
return jdbcTemplate;
}
4.2方案2:通过形参传入方式注入
// 通过形参方式赋值
public JdbcTemplate jdbcTemplate(DruidDataSource dataSource){
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(dataSource);
return jdbcTemplate;
}
注意:如果有多个组件,则形参的名称应该改为对方的Bean id。
五、@import 扩展
问题引出: 当有多个配置类的时候,需要一个一个导入对应的配置类,十分麻烦,而通过@import扩展可以实现多个配置类整合成一个配置类,最后在ioc容器创造时候只需要导入一个配置类
语法 | 描述 |
---|---|
@import(com.example.MyConfiguration.class) | 导入指定的配置类。 |
@import({ConfigA.class, ConfigB.class}) | 导入多个配置类。 |
@import(com.example.*.config.*) | 使用通配符导入指定包下的所有配置类。 |
@importResource("classpath:applicationContext.xml") | 导入 XML 配置文件。 |
@importResource({"classpath:beans.xml", "classpath:datasource.xml"}) | 导入多个 XML 配置文件。 |
案例代码:
@Import(value = {JavaConfigB.class, JavaConfigC.class})
@Configuration
public class JavaConfigA {
}
应用场景:在一个项目中可以分别配置自己需要的东西,比如数据库的配置,其他的配置等等。最后通过import整合起来。
本章总结:
1.配置类和扫描注解
掌握@component-scan、@PropertySource、@Configuration三种注解的含义与用法。
2.@Bean定义组件
掌握@Bean的基本使用,会使用两种方式创建ioc容器
3.@Bean注解细节
掌握@Bean注解的命名,周期方法,作用域,与@Bean注解下DI的实现
4.import扩展
了解并会使用@import注解