Spring-SpringIoC-注解
Spring-SpringIoC-注解
xml配置组件到IoC容器的方式十分麻烦,我们可以在组件中使用注解的方式将组件添加到IoC容器中
我们可以通过配置其value属性的形式完成对id值的修改,value= 可缺省不写
注:使用注解添加组件到IoC时,组件默认的id值会直接使用类名的首字母小写形式
注解 | 说明 |
---|---|
@Component | 该注解用于描述 Spring 中的 Bean,它是一个泛化的概念,仅仅表示容器中的一个组件(Bean),并且可以作用在应用的任何层次,例如 Service 层、Dao 层等。 使用时只需将该注解标注在相应类上即可。 |
@Repository | 该注解用于将数据访问层(Dao 层)的类标识为 Spring 中的 Bean,其功能与 @Component 相同。 |
@Service | 该注解通常作用在业务层(Service 层),用于将业务层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。 |
@Controller | 该注解通常作用在控制层(如SpringMVC 的 Controller),用于将控制层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。 |
Repository中文释义:存储库
注:三层中有自己特有的注解,component更多的是将工具类或者别的组件放入IoC容器中,这四个注解在功能上没有任何区别
配置扫描包
在标记注解之后,我们还要在配置文件中增加被容器扫描的包
在spring配置文件中,我们使用context:component-scan标签进行扫描
- base-package:此属性用以配置被扫描的包,可以填写多个包名用逗号隔开,包中子包和所有类都会被递归扫描
<context:component-scan base-package="com.xiaobai.ioc_01"/>
我们在软编码jdbc配置文件时,使用context:property-placeholder标签导入了jdbc.properties
context:exclude-filter
在使用context:component-scan标签时,可以使用其子标签context:exclude-filter进行包的排除
- type:排除的类型
- expression:排除具体的类
<context:component-scan base-package="com.xiaobai">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
以上代码就是,使用spring接管了com.xiaobai包下所有带注解的组件,但排除注解为Repository的组件
context:include-filter
在使用context:component-scan标签时,为其添加属性use-default-filters为false,指定包不生效
再使用其子标签context:include-filter进行指定包的扫描
<context:component-scan base-package="com.xiaobai" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
以上代码就是,spring不扫描com.xiaobai包下所有带注解的组件,只扫描注解为Repository的组件
周期方法
与xml配置周期方法的方式大同小异,使用注解即可配置生命周期方法
- @PostConstrct:指定初始化方法
- @ProDestroy:指定销毁方法
注:这两个注解必须要导入javax.annotation依赖,才可以使用
注:这个依赖已经更新为jakarta.annotation依赖,javax是过去式了
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Component
public class JavaBean {
@PostConstruct
public void init(){
}
@PreDestroy
public void destroy(){
}
}
作用域配置
与xml配置作用域方式大同小异,使用注解可配置组件的作用域
- @Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON):配置单例作用域(默认值)
- @Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE):配置多例作用域
具体的作用域信息可在 笔记 -> Spring-SpringIoC -> 组件的作用域和周期方法 -> 作用域 找到
@Component
@Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON) //单例 默认值
@Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE) //多例
public class JavaBean {
……
}
DI
@AutoWired
与xml配置DI的方式不同,注解配置DI的方式是使用@AutoWired实现自动装配
public class UserController {
@Autowired
private UserService userService;
}
@Autowired注解会在IoC容器中寻找组件,寻找到符合UserService接口的实现类(或者类本身),就将组件对象自动装配到此属性中
所以,@Autowired注解是直接对属性进行的操作,不需要有setter就可以实现
这个注解不止可以加在属性上,也可以加在构造方法或setter方法上,实现自动装配
在实际开发当中,我们最常使用的就是Autowired自动装配到属性 😊
佛系装配
自动装配时,@AutoWired注解的required值默认为true,也就是要求有对应的接口实现类来装配
而我们可以手动设置required值为false,则不强制要求有对应的接口实现类来装配
@Autowired(required = false)
但如果有调用容器,则会报空指针异常!!!!
所以不推荐使用佛系装配,除非你装配的属性不会被使用
@Qualifier
以上的自动装配情况有一个前提,这一个属性只对应一个组件,即根据接口的属性类型只查找到一个接口的实现类
当根据属性类型查找到多个组件时,再去通过属性名找组件
那如果接口下有两个实现类,我们也可以通过成员属性名的方式来进行区分
- 方式1:将成员属性名改成实现类的名字,在自动装配时会根据这个属性名去找实现类组件对象进行装配(更改需求)
- 方式2:将组件id值改成接口的名字的首字母小写的名字,在自动装配时也会根据属性名找到被更改的组件ID,进行装配(更改供给)
这两个方案都不够好,IoC容器提供了一个新的注解@Qualifier来解决此问题
qualifier中文释义:入围者
接口的属性值value可以指定组件对象进行装配,必须配合Autowired进行使用,value可以省略
public class UserController {
@Autowired
@Qualifier("userServiceImpl")
private UserService userService;
}
@Resource
JSR(Java Specification Requests)是Java平台标准化进程中的一种技术规范,而JSR注解是其中一部分重要的内容
JSR-250提供了@Resource注解,这个注解由java提供,由spring实现
注:这个注解也必须要导入jakarta.annotation依赖,才可以使用
@Resource注解 = @Autowired注解 + @qualifire注解
它提供了一个属性name,作用与@qualifire注解的属性value相同
public class UserController {
@Resource(name = "userServiceImpl")
private UserService userService;
}
@Value
基本数据类型也可以通过注解的方式来赋值,使用@Value注解即可
public class JavaBean {
@Value("xiaobai")
String name;
}
我们也可以使用properties外部文件,在spring配置文件中使用context加载配置文件后,在注解里使用${}获取值赋值给属性
jdbc.user=root
jdbc.password=Zhuwenxue2002
<context:component-scan base-package="com.xiaobai.ioc_03"/>
<context:property-placeholder location="classpath:jdbc.properties"/>
@Component
public class JavaBean {
@Value("${jdbc.username}")
String username; // root
@Value("${jdbc.password}")
String userPwd; // Zhuwenxue2002
}
我们可以在使用:默认值语法来为数据添加默认值
@Component
public class JavaBean {
@Value("${jdbc.username:root}")
String username;
}
以上代码为:当jdbc.username为空时,username的值为默认值root
xml
当使用注解替代xml之后,xml的作用就变得更精简了
- 使用<context:component-scan base-package=""/>标签配置扫描包
- 使用<context:property-placeholder location=""/>引入外部的配置文件
- location属性中的classpath表示相对路径,在项目中查找资源文件,再查找jar包
- 第三方类的IoC配置
注解也没办法将第三方jar包放到IoC容器,也无法为这个jar包实现DI
比如之前我们学习的Druid和JdbcTemplate使用
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="${jdbc.url}"/>
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
我们无法在Druid和JdbcTemplate添加注解,将其放入IoC容器
也无法为JdbcTemplate配置@Autowired注解,让其实现自动注入连接池
所以目前来说,我们只能使用xml完成第三方类的配置
**当然,第三方类也是被放入IoC容器中,在Dao使用JdbcTemplate时也是可以直接使用@Automired自动装配的方式 ** 😐