Spring注解版–Spring自动装配:
最近在看spring注解的网上视频教程,为了以后回头看看,我将内容写了下来,如下:
文章目录
1.环境配置
1.1、创建一个Maven工厂
我们在idea中创建一个maven的quickstart工程。
我们在pom.xml依赖中添加需要添加的依赖。
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.2.RELEASE</version>
</dependency>
</dependencies>
1.2、创建相关的类
- 创建dao数据访问层
我们在目录下创建dao包,在此包下面创建一个MyDao的类文件,此文件的类名上面添加了注解@Repository
。
MyDao:
package com.xiaojian.dao;
import org.springframework.stereotype.Repository;
@Repository
public class MyDao {
}
- 创建service服务层
我们在目录下创建service包,在此包下面创建MyService的类文件,此文件的类名上面添加了注解@Service
。
MyService:
package com.xiaojian.service;
import com.xiaojian.dao.MyDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Autowired
private MyDao myDao;
@Override
public String toString() {
return "MyService{" +
"myDao=" + myDao +
'}';
}
}
- 创建controller控制器
我们在目录下创建controller包,在此包下面创建一个MyController的类文件,此文件的类名上面添加了注解@Controller
。
MyController:
package com.xiaojian.controller;
import com.xiaojian.service.MyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class MyController {
@Autowired
private MyService myService;
@Override
public String toString() {
return "MyController{" +
"myService=" + myService +
'}';
}
}
2.自动装配:
Spring利用依赖注入(DI),完成对IOC容器中各个组件的依赖关系的赋值。
2.1、@Autowired
自动注入(spring注解)
2.1.1、@Autowired
注入实例
2.1.1.1、创建配置类
我们在目录下创建config包,在此包下面创建MainConfigOfAutowired类文件,此类作为配置类。
MainConfigOfAutowired:
package com.xiaojian.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration //此类作为配置类
//扫描service、dao、controller三个包下面的配置类。
@ComponentScan({"com.xiaojian.service","com.xiaojian.dao","com.xiaojian.controller"})
public class MainConfigOfAutowired {
}
2.1.1.2、创建测试类
我们在目录下创建test包,在此包下面创建Test_MainConfigOfAutowired类文件。
Test_MainConfigOfAutowired:
package com.xiaojian.test;
import com.xiaojian.config.MainConfigOfAutowired;
import com.xiaojian.dao.MyDao;
import com.xiaojian.service.MyService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Test_MainConfigOfAutowired {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(MainConfigOfAutowired.class);
//看看myservice这个对象里面注入的mydao的信息
MyService myService = applicationContext.getBean(MyService.class);
System.out.println(myService);
//看看mydao这个对象的信息
MyDao myDao = applicationContext.getBean(MyDao.class);
System.out.println(myDao);
applicationContext.close();
}
}
2.1.1.3、测试运行
运行Test_MainConfigOfAutowired测试类,测试结果:
D:\basic\jdk\jdk1.8.0_131\bin\java ...
MyService{myDao=com.xiaojian.dao.MyDao@3d3fcdb0}
com.xiaojian.dao.MyDao@3d3fcdb0
Process finished with exit code 0
如上,在MyService这个对象中,它内部的mydao是3d3fcdb0,而我们IOC容器中本身的MyDao这个对象为3d3fcdb0,所以我们在MyService中通过@Autowired
注解注入的MyDao是成功的。
2.1.2、@Autowired
与@Bean
对比
2.1.2.1、修改MyDao数据访问层
MyDao:
package com.xiaojian.dao;
import org.springframework.stereotype.Repository;
//名字默认是类名的小写首字母的方式
@Repository
public class MyDao {
//此处默认为1
private String label = "1";
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
@Override
public String toString() {
return "MyDao{" +
"label='" + label + '\'' +
'}';
}
}
2.1.2.2、修改MainConfigOfAutowired配置类
MainConfigOfAutowired:
package com.xiaojian.config;
import com.xiaojian.dao.MyDao;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan({"com.xiaojian.service","com.xiaojian.dao","com.xiaojian.controller"})
public class MainConfigOfAutowired {
//此处是我们在配置类中添加的一个Bean,此处我们命名为myDao2,与MyService中@Autowired注入的mydao1区分开来。
@Bean("myDao2")
public MyDao myDao(){
MyDao myDao=new MyDao();
myDao.setLabel("2");
return myDao;
}
}
我们在此类中添加一个bean的注册,目的在于看看我们在MyService类文件中通过@Autowired
注解注入的MyDao是系统配置类的还是bean注册的。
2.1.2.3、修改测试类
我们修改Test_MainConfigOfAutowired测试类。
Test_MainConfigOfAutowired:
package com.xiaojian.test;
import com.xiaojian.config.MainConfigOfAutowired;
import com.xiaojian.dao.MyDao;
import com.xiaojian.service.MyService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Test_MainConfigOfAutowired {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(MainConfigOfAutowired.class);
//看看myservice这个对象里面注入的mydao的信息
MyService myService = applicationContext.getBean(MyService.class);
System.out.println(myService);
applicationContext.close();
}
}
2.1.2.4、测试运行
运行Test_MainConfigOfAutowired配置类。
测试结果:
D:\basic\jdk\jdk1.8.0_131\bin\java ...
MyService{myDao=MyDao{label='1'}}
Process finished with exit code 0
如上,控制台打印出了MyService中的通过@Autowired
注解注入的MyDao是来自MyDao这个配置类来的,而不是来自@Bean
注解注入进来的。
2.1.1.5、总结:
- 系统默认优先按照类型去容器中找到对应的组件,找到就给他赋值;
- 当系统有多个相同类型的组件的时候,我们通过
@Autowired
注解注入的内容,是系统通过配置类注入进IOC的对象,而不是通过@Bean
注入的内容。
如果将MyService中的MyDao属性改成mydao2,那么系统通过
@Autowired
注解注入的mydao2就是通过@Bean
注入进IOC中的内容。@Autowired private MyDao myDao2;
- 当系统找到多个相同类型的组件的时候,我们将属性的名称作为组件的id去容器中查找,因为通过类型去查找,我们会查找出多个,所以无法查找。
- (重要!)自动装配的时候,我们默认一定要将属性值赋值好,否则会报错,因为系统找不到IOC容器中有bean,所以一定要赋值好。
如果存在没赋值好的时候,我们可以将
@Autowired
注解的required属性设置为false来解决这个问题。设置这个属性后,如果没有赋值好,此处也没有问题,就是不会将此注解标注的mydao装配到类中。@Autowired(required = false)
2.1.3、@Qualifier
注解指定装配
我们除了用上面方法装配组件,我们可以通过@Qualifier
指定需要装配的组件的id,而不是使用属性名。
2.1.3.1、修改MyService服务层
我们修改MyService类文件,将需要自动装配的mydao这个属性添加注解@Qualifier
。
MyService:
package com.xiaojian.service;
import com.xiaojian.dao.MyDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Qualifier("myDao2") //此处通过@Qualifier指定装配myDao2,也就是指定装配通过@Bean注册的组件。
@Autowired
private MyDao myDao;
@Override
public String toString() {
return "MyService{" +
"myDao=" + myDao +
'}';
}
}
2.1.3.1、测试运行
我们运行测试类Test_MainConfigOfAutowired,测试结果:
D:\basic\jdk\jdk1.8.0_131\bin\java ...
MyService{myDao=MyDao{label='2'}}
Process finished with exit code 0
如上,我们通过注解@Qualifier
指定自动配置中注入的内容的来源,此处就是来自IOC容器中通过@Bean
注册的bean对象。
2.1.4、@Primary
注解
让spring进行自动装配的时候,默认使用首选的bean(如果使用了@Qualifier
注解指定了,那么就装配其指定的bean对象)。
2.1.4.1、修改MainConfigOfAutowired配置类
我们将MainConfigOfAutowired配置类中的bean添加注解@Primary
,将其设置为首选的bean的配置。
MainConfigOfAutowired:
package com.xiaojian.config;
import com.xiaojian.dao.MyDao;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@Configuration
@ComponentScan({"com.xiaojian.service","com.xiaojian.dao","com.xiaojian.controller"})
public class MainConfigOfAutowired {
//此处添加@Primary注解,将其设置为首选的bean注册
@Primary
@Bean("myDao2")
public MyDao myDao(){
MyDao myDao=new MyDao();
myDao.setLabel("2");
return myDao;
}
}
2.1.4.2、修改MyService服务层
package com.xiaojian.service;
import com.xiaojian.dao.MyDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service
public class MyService {
// @Qualifier("myDao2")
// @Autowired(required = false)
//此处还原成最原先的,不添加其他的任何注解
@Autowired
private MyDao myDao;
@Override
public String toString() {
return "MyService{" +
"myDao=" + myDao +
'}';
}
}
2.1.4.3、测试运行
运行测试类Test_MainConfigOfAutowired,测试结果:
D:\basic\jdk\jdk1.8.0_131\bin\java ...
MyService{myDao=MyDao{label='2'}}
Process finished with exit code 0
如上,系统的控制台打印除了label=2这个,说明我们MyService中通过注解@Autowired
自动配置的MyDao是通过@Primay
注解注册的bean对象。
2.2、@Resource
自动注入(Java规范注解)
2.2.1、修改MyService服务层
package com.xiaojian.service;
import com.xiaojian.dao.MyDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class MyService {
// @Qualifier("myDao2")
// @Autowired(required = false)
// @Autowired
@Resource //此处添加@Resource
private MyDao myDao;
@Override
public String toString() {
return "MyService{" +
"myDao=" + myDao +
'}';
}
}
2.3.2、测试运行
运行测试类Test_MainConfigOfAutowired,运行结果如下:
D:\basic\jdk\jdk1.8.0_131\bin\java ...
MyService{myDao=MyDao{label='1'}}
Process finished with exit code 0
如上,系统给MyService中添加了@Resource
注解的mydao
属性自动注入了通过@Repository
注入到IOC容器中的bean对象,而不是通过@Bean
注解注入到IOC容器中的bean对象。
2.3.3、总结
@Resource
注解使用总结:
@Resource
可以实现自动装配的功能,但是其默认按照组件名称装配。- 没有能够支持
@Primary
注解的功能,也没有支持@Autowired(required=false)
的功能 - 其默认按照
@Repository
注解注入到IOC容器中的对象,而不是通过@Bean
注解注入到IOC容器中的bean对象。 - 我们可以通过
@Resource(name="xxxx")
来指定装配对象。
@Resource(name = "myDao2")
2.3、@Inject
自动注入(Java规范注解)
@Inject
注解的使用功能和@Autowired
注解是一样的。
2.3.1、导入相关的依赖
我们想要使用这个注解,必须导入其他的相关的依赖。
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
2.3.2、修改MyService服务层
package com.xiaojian.service;
import com.xiaojian.dao.MyDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.inject.Inject;
@Service
public class MyService {
// @Qualifier("myDao2")
// @Autowired(required = false)
// @Autowired
// @Resource(name = "myDao2")
@Inject //此处使用@inject注解来自动注入
private MyDao myDao;
@Override
public String toString() {
return "MyService{" +
"myDao=" + myDao +
'}';
}
}
2.3.3、测试运行
2.3.3.1、配置类的bean方法上添加@primary
注解
(因为我在MainConfigOfAutowired中没有改变,所以在bean对象的创建上面,我还是添加了@primary
注解)
运行测试类Test_MainConfigOfAutowired,测试结果:
D:\basic\jdk\jdk1.8.0_131\bin\java ...
MyService{myDao=MyDao{label='2'}}
Process finished with exit code 0
如上,此处打印的是label=2,说明此处注入的是MainConfigOfAutowired配置类中的bean方法创建的bean对象,因为我在此方法上面添加了@Primary
注解,所以才会打印这个。
2.3.3.2、配置类的bean方法上未添加@Primary
注解
运行测试类Test_MainConfigOfAutowired,测试结果:
D:\basic\jdk\jdk1.8.0_131\bin\java ...
MyService{myDao=MyDao{label='1'}}
Process finished with exit code 0
如上,此处打印的是label=1,说明此处注入的是@Repository
注解注入的对象。