3.2.注解方式
目前 主流的方式 是使用注解方式来实现IoC效果.
3.2.1.配置类
在 config
包下增加 SpringConfig
配置类
@Configuration
声明当前类为配置类, SpringIoC容器会根据配置类信息进行配置
@ComponentScan()
bean扫描路径 , SpringIoC容器只维护 声明的路径下的增加"组件注解"的类
如果没有指定具体的路径 , SpringIoC容器 扫描@ComponentScan注解的类所在的包及其子包
package com.yuan.spring.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.yuan.spring.beans")
public class SpringConfig {
}
3.2.2.组件注解
@Component
, @Controller
, @Service
, @Repository
作用是一样的
加载在类上, 如果类在@ComponentScan 声明的扫描路径上, 将会被SpringIoC容器扫描到
@Component
public class HouWang {
...
}
3.2.3.基于配置类的IoC容器
// 基于配置类创建 IoC容器
AbstractApplicationContext beanFactory = new AnnotationConfigApplicationContext(SpringConfig.class);
// 得 bean的实例
HouWang houWang = beanFactory.getBean(HouWang.class);
3.2.4.注入简单值
在私有属性上使用 @Value
为属性赋值 , 属性的setter/getter方法可以去掉
@Value("齐天大圣")
private String mingZi;
public void daZhaoHu() {
System.out.println("大家好,我是" + this.mingZi);
}
//public String getMingZi() {
// return mingZi;
//}
//
//public void setMingZi(String mingZi) {
// this.mingZi = mingZi;
//}
调用方法测试
// 基于配置类创建 IoC容器
AbstractApplicationContext beanFactory = new AnnotationConfigApplicationContext(SpringConfig.class);
// 得 bean的实例
HouWang houWang = beanFactory.getBean(HouWang.class);
// 调用 打招呼的方法
houWang.daZhaoHu();
3.2.5.注入对象类型
Spring使用 @Autowired
、@Resource
注解标记依赖项,并自动解析和注入它们。
3.2.5.1.@Autowired 注入
在 TieShanGongZhu 铁扇公主 类
上增加@Component注解,
注册到SpringIoC容器上, 由SpringIoC容器来实例化
@Component
public class TieShanGongZhu implements IYaoGuai {
...
}
再修改 HouWang 猴王类
, 在 IYaoGuai 属性增加 @Autowired
注解
@Autowired
private IYaoGuai yg;
//public IYaoGuai getYg() {
// return yg;
//}
//
//public void setYg(IYaoGuai yg) {
// this.yg = yg;
//}
public void daYaoGuai() {
//TieShanGongZhu yg = new TieShanGongZhu();
yg.beiDa();
}
测试
// 基于配置类创建 IoC容器
AbstractApplicationContext beanFactory = new AnnotationConfigApplicationContext(SpringConfig.class);
// 得 bean的实例
HouWang houWang = beanFactory.getBean(HouWang.class);
// 调用 打妖怪方法
houWang.daYaoGuai();
得到 结果, 说明 通过@Autowired 将 TieShanGongZhu 铁扇公主 类
的实例注入到 HouWang 猴王类
中
石破天惊
我是公主!
臭猴子,肚子疼!
3.2.5.2.多个匹配出现冲突
给 NiuMoWang 牛魔王 类
增加@Component注解,
注册到SpringIoC容器上, 由SpringIoC容器来实例化
@Component
public class NiuMoWang implements IYaoGuai {
...
}
这样 就有 NiuMoWang 牛魔王 类
, TieShanGongZhu 铁扇公主 类
都满足 HouWang 猴王类
的注入要求
两个类都是 IYaoGuai 妖怪接口
的实现类, SpringIoC容器会注入哪个呢?
运行测试 ,
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'houWang': Unsatisfied dependency expressed through field 'yg'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.yuan.spring.beans.IYaoGuai' available: expected single matching bean but found 2: niuMoWang,tieShanGongZhu
报错 : 预计单一匹配, 但找到了2个 : niuMoWang , tieShanGongZhu
说明 @Autowired 是按照类型进行匹配的
同时, SpringIoC容器在实例化对象时, 分别给类的实例起别名niuMoWang , tieShanGongZhu ( 类名首字母小写 )
有以下几种解决方案:
- 修改类实例的别名 , 在@Component(“别名”) , 这里的别名与注入的变量名相同 如: “yg”
- 直接修改应用类中需要注入的变量名与要注入的实例的默认别名相同
- 在变量名上增加 @Qualifier(“niuMoWang”) 与注入的实例的默认别名相同
- 可以使用 @Resource(name = “niuMoWang”) 来替换 @Autowired
3.2.5.3.@Autowired 与 @Resource
@Autowired
和 @Resource
都是用于进行依赖注入的注解,但它们的具体使用有一些不同。
@Autowired
是 Spring 框架的注解,可以自动装配一个 bean 到使用它的类中。Spring 在容器启动时,自动扫描类路径中的组件(带有 @Component
或其它特定注解的类),并为其创建 bean。如果有多个 bean 满足装配的需求,可以通过指定 Qualifier 或者通过 Primary 注解来进行区分。
@Resource
是 Java 的标准注解,可以标注在属性、方法或构造函数上,指定需要装配的 bean 名称作为参数。如果没有指定名称,则会使用默认规则查找匹配的 bean。需要注意的是,@Resource
不支持 Qualifier 和 Primary 注解。
综上所述,@Autowired
更为灵活,支持 Qualifier 和 Primary 注解,适用于大部分情况下的依赖注入。@Resource
则更为简单,适用于只有一个符合条件的 bean 需要装配的情况。
3.2.6.@Bean声明注册
在 Spring 框架中,使用 @Bean 注解可以将某个方法的返回值注入到容器中,使之成为一个可被管理的 bean。
具体使用方式如下:
- 在 Java 配置类中,使用 @Configuration 注解,声明一个类为配置类。
- 在该类中,使用 @Bean 注解,声明一个方法为 Bean 方法,并在该方法中返回一个实例。
- 然后,Spring 容器会自动扫描该配置类,将其加载到 ApplicationContext 容器中,并在需要的时候使用该 Bean。
下面是一个简单的示例代码,展示了如何使用 @Bean 注解:
package com.yuan.spring.config;
import com.yuan.spring.beans.HongHair;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.yuan.spring.beans")
public class SpringConfig {
@Bean("hongHair")
public HongHair getHongHair(){
return new HongHair();
}
}
需要注意的是,@Bean 注解有许多属性,可以用来定义 Bean 的各种属性,比如名称、作用域、依赖等等。此外,若多处出现名称相同的 bean,需要使用 @Qualifier
或 @Primary
注解来指定要注入的 bean。