文章目录
基于 注解 方式管理 Bean
- 和 XML 配置文件一样,注解本身并不能执行,注解本身仅仅只是做一个标记
- 具体的功能是:
- 框架检测到注解标记的位置,然后针对这个位置按照注解标记的功能来执行具体操作。
- 本质上:
- 所有一切的操作都是 Java 代码来完成的,XML 和注解只是告诉框架中的 Java 代码如何执行。
一、Bean注解标记和扫描 (IoC)
注解 (标记)+ XML(扫描)
- 注解方式IoC只是标记哪些类要被Spring管理
- 最终,我们还需要XML方式或者Java配置类方式指定注解生效的包
Spring 为了知道程序员在哪些地方标记了什么注解,就需要通过扫描的方式,来进行检测。然后根据注解进行后续操作。
1.1 组件注解介绍
注解 | 说明 |
---|---|
@Component | 该注解用于描述 Spring 中的 Bean,它是一个泛化的概念,仅仅表示容器中的一个组件(Bean),并且可以作用在应用的任何层次,例如 Service 层、Dao 层等。 使用时只需将该注解标注在相应类上即可。 |
@Repository | 该注解用于将数据访问层(Dao 层)的类标识为 Spring 中的 Bean,其功能与 @Component 相同。 |
@Service | 该注解通常作用在业务层(Service 层),用于将业务层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。 |
@Controller | 该注解通常作用在控制层(如SpringMVC 的 Controller),用于将控制层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。 |
![]() | |
通过查看源码我们得知,@Controller、@Service、@Repository这三个注解只是在@Component注解的基础上起了三个新的名字。 |
@Controller、@Service、@Repository 本质上是一样,只是给开发人员看的,让我们能够便于分辨组件的作用,为了代码的可读性、程序结构严谨。
1.2 标记组件
/**
* @Description: 普通的组件
*/
@Component
public class JavaCompontent {
}
/**
* @Description: Controller类型组件
*/
@Controller
public class XxxController {
}
/**
* @Description: service类型组件
*/
@Service
public class XxxService {
}
/**
* @Description: dao层类型组件
*/
@Repository
public class XxxDao {
}
1.3 配置文件确定扫描范围
<!-- 1. 普通配置包扫描
base-package 扫描这个包下全部的类(可以一个包 或 多包)
-->
<context:component-scan base-package="com.doug.ioc01"/>
<!-- 2. 指定包,但是排除注解 -->
<!-- context:exclude-filter标签:指定排除规则 -->
<!-- type属性:指定根据什么来进行排除,annotation取值表示根据注解来排除 -->
<!-- expression属性:指定排除规则的表达式,对于注解来说指定全类名即可 -->
<context:component-scan base-package="com.doug">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 3. 指定包,指定包含的注解 -->
<!-- 仅扫描 = 关闭默认规则 + 追加规则 -->
<!-- use-default-filters属性:取值false表示关闭默认扫描规则 -->
<context:component-scan base-package="com.doug" use-default-filters="false">
<!-- context:include-filter标签:指定在原有扫描规则的基础上追加的规则 -->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
1.4 组件BeanName问题
默认情况:
类名首字母小写就是 bean 的 id。
例如:SoldierController 类对应的 bean 的 id 就是 soldierController。
使用value属性指定:
@Controller(value = "myController")
public class XxxController {
}
当注解中只设置一个属性时,value属性的属性名可以省略:
@Controller("myController")
public class XxxController {
}
二、组件(Bean)作用域和周期方法注解
@Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON) //单例,默认值
@Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE) //多例 二选一
public class BeanOne {
//周期方法要求: 方法命名随意,但是要求方法必须是 public void 无形参列表
@PostConstruct //注解制指定初始化方法
public void init() {
// 初始化逻辑
}
}
public class BeanTwo {
@PreDestroy //注解指定销毁方法
public void cleanup() {
// 释放资源逻辑
}
}
三、Bean属性赋值:引用类型自动装配 (DI)
- @Autowired注解
- 使用此直接 自动装配 引用类型成员属性
- 能够找到唯一的 bean:直接执行装配
- 如果完全找不到匹配这个类型的 bean:装配失败
@Controller("myController")
public class XxxController {
@Autowired
private XxxService serviceImpl;
public void show(){}
}
- 类型匹配的 bean 不止一个
- 没有 @Qualifier 注解:根据 @Autowired 标记位置成员变量的变量名作为 bean 的 id 进行匹配
- 能够找到:执行装配
- 找不到:装配失败
- 使用 @Qualifier 注解:根据 @Qualifier 注解中指定的名称作为 bean 的id进行匹配
- 能够找到:执行装配
- 找不到:装配失败
- 没有 @Qualifier 注解:根据 @Autowired 标记位置成员变量的变量名作为 bean 的 id 进行匹配
@Controller("myController")
public class XxxController {
// <property xxxservice -> 对应类型的bean装配
//自动装配注解(DI) : 1. IOC容器中查找符合类型的组件对象 2. 设置给当前属性(DI)
@Autowired
@Qualifier(value = "xxxService")
private XxxService serviceImpl;
public void show(){}
}
- 指定 单个 引用类型装配 使用
@Autowired
注解- 有多个引用类型的类 存在 使用
@Autowired + @Qualifier(指定类名)
@Autowired + @Qualifier(指定类名) == 注解@Resource(指定类名)
@Resource
: 标识一个需要注入的资源,是实现Java EE组件之间依赖关系的一种方式。
使用 注解@Resource ,需要导入依赖:
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>2.1.1</version>
</dependency>
@Resource使用 :
@Controller
public class XxxController {
/**
* 1. 如果没有指定name,先根据属性名查找IoC中组件xxxService
* 2. 如果没有指定name,并且属性名没有对应的组件,会根据属性类型查找
* 3. 可以指定name名称查找! @Resource(name='test') == @Autowired + @Qualifier(value='test')
*/
@Resource
private XxxService xxxService;
//@Resource(name = "指定beanName")
//private XxxService xxxService;
public void show(){
System.out.println("XxxController.show");
xxxService.show();
}
}
四、Bean属性赋值:基本类型属性赋值 (DI)
@Value
通常用于注入外部化属性
@Component
public class JavaBean {
/*
* 1. 直接赋值
* 2. 注解赋值:
* 2.1 @Value注解 直接/读取外部配置
* 默认语法:
* @Value("value")
* @Value("${key}") @Value("${key:value}")
* */
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password:000000}")
private String pwd;
@Value("18")
private int age;
private String value = "道格";
@Override
public String toString() {
return "JavaBean{" +
"username='" + username + '\'' +
", pwd='" + pwd + '\'' +
", age=" + age +
", value='" + value + '\'' +
'}';
}
}
五、基于注解+XML方式整合三层架构组件
加注解,但dao层 导入第三方类 所以还是要在xml里面配置bean
总结
- 自定义类可以使用注解方式,但是第三方依赖的类依然使用XML方式!
- XML格式解析效率低!