基于XML配置文件的DI请参考上文
https://blog.csdn.net/MinggeQingchun/article/details/122880488
DI 使用注解,将不再需要在 Spring 配置文件中声明 bean 实例
Spring 中使用注解,需要在 Spring 配置文件中配置组件扫描器,用于在指定的基本包中扫描注解
1、声明组件扫描器(component-scan),组件就是Java对象
base-package:指定注解在项目中的包名
2、component-scan工作原理:
spring会扫描遍历base-package指定的包, 扫描包和子包中的所有类,找到类中的注解,按照注解创建Java对象,或者给属性赋值
3、加入
(1)加入了新的约束文件:spring-context.xsd
(2)给这个新的约束文件起个命名空间的名称
xmlns:context="http://www.springframework.org/schema/context" http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.x

4、指定多个包的3种方式
(1)使用多个 context:component-scan 指定不同的包路径
- <context:component-scan base-package="com.mycompany.package1" />
- <context:component-scan base-package="com.mycompany.package2" />
(2)指定 base-package 的值使用分隔符
分隔符可以使用逗号(,)分号(;)还可以使用空格,不建议使用空格
<context:component-scan base-package="com.mycompany.package1;com.mycompany.package2" />
(3)base-package 是指定到父包名
但不建议直接使用com,这样会扫描磁盘中所有文件夹,导致效率降低
<context:component-scan base-package="com.mycompany" />
spring配置文件 applicationContext.xml
- <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
- https://www.springframework.org/schema/context/spring-context.xsd">
-
-
-
- <context:component-scan base-package="com.mycompany.p2valuenormal" />
-
-
-
- <context:property-placeholder location="classpath:objectvalue.properties" />
-
-
-
-
-
- beans>
(一)@Component、@Repository、@Service、@Controller注解
1、@Component :创建对象,等同
(1)属性:value 对象的名称,就是
(2)位置:类上面
(3)语法:
- @Component(value = "myUser")
-
- 等同
-
"myUser" class="com.xx.User" />
spring中和@Component功能一致,创建对象的注解还有:
1、@Repository(持久层类的上面):放在dao的实现类上面, 表示创建dao对象,dao对象是能访问数据库的
2、@Service (业务层类的上面):放在service的实现类上面, 创建service对象,service对象是做业务处理,可以有事务等功能的
3、@Controller (控制器的上面):放在控制器(处理器)类的上面,创建控制器对象的, 控制器对象,能够接受用户提交的参数,显示请求的处理结果
以上三个注解的使用语法和@Component一样的,都能创建对象,但是这三个注解还有额外的功能
@Repository ,@Service,@Controller是给项目的对象分层的
@Component有3中用法
(1)使用value属性,指定对象名称 @Component(value = "myUser")
(2)省略value关键字 @Component("myUser")
(3)不指定对象名称,由spring提供默认名称: 类名的首字母小写 @Component
- /*
- 1、使用value属性,指定对象名称
- @Component(value = "myUser")
- 2、省略value关键字
- @Component("myUser")
- 3、不指定对象名称,由spring提供默认名称: 类名的首字母小写
- @Component
- */
-
- //使用value属性,指定对象名称
- @Component(value = "myUser")
- public class User {
- }
测试代码
- @Test
- public void testComponent(){
- String config = "applicationContext.xml";
- ApplicationContext ac = new ClassPathXmlApplicationContext(config);
-
- User user = (User) ac.getBean("myUser");
-
- //不指定对象名称,由spring提供默认名称: 类名的首字母小写 @Component
- // User user = (User) ac.getBean("user");
- System.out.println(user);
- }
(二)@Value简单类型赋值
@Value : 简单类型属性赋值
(1)属性: value
【1】String类型,表示简单类型属性值
【2】也可使用属性配置文件加载,@Value("${属性的key}")
在 applicationContext.xml 文件中加载属性配置文件
- <context:property-placeholder location="classpath:objectvalue.properties" />
objectvalue.properties属性配置文件
- myName=admin
- myAge=18
使用
- @Value("${myName}")//使用属性配置文件中的数据
- private String userName;
- // @Value("18")
- @Value("${myAge}")//使用属性配置文件中的数据
- private int age;
(2)位置: 1、在属性定义上面,无需set方法(建议使用);2、在set方法上面
- //使用value属性,指定对象名称
- @Component(value = "myUser")
- public class User {
- /**
- * @Value : 简单类型属性赋值
- * 属性: value String类型,表示简单类型属性值
- * 也可使用属性配置文件加载,@Value("${属性的key}")
- * 位置: 1、在属性定义上面,无需set方法(建议使用)
- * 2、在set方法上面
- */
- // @Value("admin")
- @Value("${myName}")//使用属性配置文件中的数据
- private String userName;
- // @Value("18")
- @Value("${myAge}")//使用属性配置文件中的数据
- private int age;
-
- public User() {
- System.out.println("spring会调用User类的无参构造方法创建对象");
- }
-
- // @Value("admin")
- public void setUserName(String userName) {
- this.userName = userName;
- }
-
- // @Value("18")
- public void setAge(int age) {
- this.age = age;
- }
- }
(三)@Autowired
1、byType
@Autowired 默认使用的是 byType自动注入
位置: 1、在属性定义的上面,无需set方法(建议使用) 2、在set方法的上面
- //使用value属性,指定对象名称
- @Component(value = "myUser")
- public class User {
-
- /**
- * 引用类型 @Autowired(byType)
- * @Autowired :spring框架提供的注解,实现引用类型赋值
- * spring通过注解给引用类型赋值,使用的是自动注入原理,支持 byName,byType
- * @Autowired 默认使用的是 byType自动注入
- *
- * 位置:
- * 1、在属性定义的上面,无需set方法(建议使用)
- * 2、在set方法的上面
- */
- @Autowired
- private Address address;
-
- }
-
- @Component(value = "myAddress")
- public class Address {
- }
2、byName和@Qualifier
@Autowired使用byName方式
在属性上加入 @Autowired;在属性上还要加上@Qualifier(value = "bean的id"):表示使用指定名称的bean完成赋值
注:@Autowired 和 @Qualifier 注解没有先后顺序之分,一般先声明功能,将@Autowired写在上面
- //使用value属性,指定对象名称
- @Component(value = "myUser")
- public class User {
-
- @Value("admin")
- // @Value("${myName}")//使用属性配置文件中的数据
- private String userName;
- @Value("18")
- // @Value("${myAge}")//使用属性配置文件中的数据
- private int age;
-
- /**
- * 引用类型 @Autowired(byType)
- * @Autowired :spring框架提供的注解,实现引用类型赋值
- * spring通过注解给引用类型赋值,使用的是自动注入原理,支持 byName,byType
- * 1、@Autowired 默认使用的是 byType自动注入
- * 位置:
- * (1)在属性定义的上面,无需set方法(建议使用)
- * (2)在set方法的上面
- *
- * 2、@Autowired使用byName方式
- * 在属性上加入 @Autowired;
- * 在属性上还要加上@Qualifier(value = "bean的id"):表示使用指定名称的bean完成赋值
- * 注:
- * @Autowired 和 @Qualifier 注解没有先后顺序之分,一般先声明功能,将@Autowired写在上面
- */
- @Autowired
- @Qualifier("myAddress")
- private Address address;
-
- }
-
-
- @Component(value = "myAddress")
- public class Address {
- }
3、required属性
required 属性,是一个Boolean类型,默认 true
required = true :表示引用类型赋值失败,程序报错,并终止执行
required = false :表示引用类型赋值失败,程序正常执行,引用类型为 null
一般无特殊请款,建议使用required = true,将问题尽早暴露,防止后续出现空指针异常
- required = true :如果spring找不到引用对象bean的id,程序报错如下
- NoSuchBeanDefinitionException: No qualifying bean of type 'com.mycompany.p5referenceautowiredrequired.Address' available:
- expected at least 1 bean which qualifies as autowire candidate. Dependency annotations:
- {@org.springframework.beans.factory.annotation.Autowired(required=true),
- @org.springframework.beans.factory.annotation.Qualifier(value=myAddress-1)}
- //使用value属性,指定对象名称
- @Component(value = "myUser")
- public class User {
-
- /**
- * 引用类型 @Autowired(byType)
- * required 属性,是一个Boolean类型,默认 true
- * required = true :表示引用类型赋值失败,程序报错,并终止执行
- * required = false :表示引用类型赋值失败,程序正常执行,引用类型为 null
- * 一般无特殊请款,建议使用required = true,将问题尽早暴露,防止后续出现空指针异常
- *
- * required = true :如果spring找不到引用对象bean的id,程序报错如下
- NoSuchBeanDefinitionException: No qualifying bean of type 'com.mycompany.p5referenceautowiredrequired.Address' available:
- expected at least 1 bean which qualifies as autowire candidate. Dependency annotations:
- {@org.springframework.beans.factory.annotation.Autowired(required=true),
- @org.springframework.beans.factory.annotation.Qualifier(value=myAddress-1)}
- *
- */
- @Autowired(required = false)
- @Qualifier("myAddress-1")
- private Address address;
- }
-
- @Component(value = "myAddress")
- public class Address {
- }
(四)@Resource
@Resource :来自JDK中的注解(包名:javax.annotation.Resource),spring框架提供了对该注解的功能支持,可以使用它给引用类型赋值
@Resource 工作原理:使用自动注入,支持byName, byType
@Resource 注解若不带任何参数,默认是 按名称的方式注入 byName(先使用byName自动注入,如果byName赋值失败,再使用byType)
位置:1、在属性定义的上面,无需set方法(建议使用);2、在set方法上面
1、默认byName,失败则使用byType
- //使用value属性,指定对象名称
- @Component(value = "myUser")
- public class User {
-
- /**
- * 引用类型 @Resource
- * @Resource :来自JDK中的注解(包名:javax.annotation.Resource),spring框架提供了对该注解的功能支持,可以使用它给引用类型赋值
- * @Resource 工作原理:使用自动注入,支持byName, byType
- * @Resource 注解若不带任何参数,默认是 按名称的方式注入 byName(先使用byName自动注入,如果byName赋值失败,再使用byType)
- * 位置:
- * 1、在属性定义的上面,无需set方法(建议使用)
- * 2、在set方法上面
- */
- //默认是byName: 先使用byName自动注入,如果byName赋值失败,再使用byType
- @Resource
- private Address address;
- }
2、使用byName
@Resource 只使用byName方式,需要增加一个属性 name;name的值为 bean 的 id名称
- //使用value属性,指定对象名称
- @Component(value = "myUser")
- public class User {
-
- /**
- * 引用类型 @Resource
- * @Resource 只使用byName方式,需要增加一个属性 name
- * name的值为 bean 的 id名称
- */
- //只使用byName
- @Resource(name = "myAddress")
- private Address address;
- }
-
- @Component(value = "myAddress")
- public class Address {
- }