目录
一, 属性注入
属性注入的优点:
属性注入的缺点
二. Setter注入
Setter注入的优点:
Setter注入的缺点:
三, 构造方法注入 (主流方式)
构造方法注入的优点
构造方法注入的缺点
四, @Autowired与@Resource区别
获取Bean对象也叫对象注入(对象装配), 指把对象取出来放到某个类中
实现对象注入有三种方法:
1.属性注入: 将对象注入到某个类的一个属性当中。
2.构造方法注入: 通过构造方法来将对象注入到类中。
3.Setter注入: 通过 SetXXX 系列方法将对象注入到类中。
对象注入的常用注解有两个: 一个是 @Autowired ,另外一个是 @Resource
一, 属性注入
文章的实体类:
package Spring.demo;
import java.time.LocalDateTime;
public class Article {
String author;
String text;
LocalDateTime createTime;
public void setAuthor(String author) {
this.author = author;
}
public void setText(String text) {
this.text = text;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
@Override
public String toString() {
return "Article{" +
"author='" + author + '\'' +
", text='" + text + '\'' +
", createTime=" + createTime +
'}';
}
}
设置两个层,Service接收前端传递的数据, 通过属性注入到Controller中,最后再App调用Controller
ArticleService类:
package Spring.demo;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
@Service
public class ArticleService {
public Article getArticle(){
// 伪代码,假装这是从前端获取到的数据,实际开发不会这样写
Article article = new Article();
article.setAuthor("李大牛");
article.setText("锄禾日当午,飞流直下三千尺");
article.setCreateTime(LocalDateTime.now());
return article;
}
}
ArticleController类:
package Spring.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Controller;
import java.time.LocalDateTime;
@Controller
public class ArticleController {
// 通过属性注入
@Autowired
private ArticleService articleService;
public Article getArticle(){
return articleService.getArticle();
}
}
启动类获取Bean:
import Spring.demo.Article;
import Spring.demo.ArticleController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
// 1.先得到 Spring 上下文对象
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
ArticleController articleController = context.getBean(ArticleController.class);
System.out.println(articleController.getArticle().toString());
}
}
这就是属性注入
然后在启动类就可以直接通过 articleController调用到toString方法
实现简单,使用简单. 只需要在使用的变量前加上一个注解@Autowired 就可以在不new对象的情况下,直接获得注入的对象
1.功能性问题: 无法注入不可变的对象(fina修饰的对象)
2.通用性问题: 只适用于IoC容器
3.违背单一设计原则: 更容易违背单一设计原则
功能性问题:
在Java语法规范中,要求final修饰的对象要么直接赋值,要么在构造方法中赋值
因此 当我们用属性注入来注入final对象时,就会报错
通用性问题:
使用属性注入的方式只适用于IoC框架,,如果将这段代码移植到其他框架上,这段代码就失效了
违背单一设计原则:
单一设计原则: 一个类或接口,只对应一种功能
因为属性注入的方式简单,因此容易被滥用,导致一些不必要的对象被注入,更容易违背单一设计原则
但在日常开发中,有时往往需要在 单一设计原则 与 性能 之间做出取舍,比如在某些前后端交互频繁的场景,将多个接口整合成一个接口,一次性发送数据,一次性接收数据,这样就可以有效减少网络连接的TCP请求次数,显著提升了性能,但这样就违背了单一设计原则,在后期的维护与升级上就会比较麻烦.
package Spring.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Controller;
import java.time.LocalDateTime;
@Controller
public class ArticleController {
private ArticleService articleService;
// 通过Setter注入 (把ArticleService对象注入给ArticleController)
@Autowired
public void setArticleService(ArticleService articleService){
this.articleService = articleService;
}
public Article getArticle(){
return articleService.getArticle();
}
}
只需要修改这部分代码即可,在启动类运行,可以获取到Bean对象
通常Setter只set的一个属性,因此比较符合单一设计原则
1.同样无法解决 final对象无法注入的问题
2.注入对象可被修改
Setter 注入提供了 setXXX 的方法,意味着你可以在任何时候、在任何地方,通过调用 setXXX 的方法来改变注入对象,所以 Setter 注入的问题是,被注入的对象可能随时被修改。
package Spring.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Controller;
import java.time.LocalDateTime;
@Controller
public class ArticleController {
private ArticleService articleService;
@Autowired
public ArticleController(ArticleService articleService){
this.articleService = articleService;
}
public Article getArticle(){
return articleService.getArticle();
}
}
这就是构造方法注入的写法,只改动了这一部分的代码
如果当前类中只存在一个构造方法时,@Autowired也可以省略
构造方法注入相比于前两种注入方法,它可以注入不可变对象,并且它只会执行一次,也不存在像 Setter 注入那样,被注入的对象随时被修改的情况,它的优点有以下 4 个:
可注入不可变对象
注入对象不会被修改
构造方法注入不会像 Setter 注入那样,构造方法在对象创建时只会执行一次,因此它不存在注入对象被随时(调用)修改的情况。
注入对象会被完全初始化
因为依赖对象是在构造方法中执行的,而构造方法是在对象创建之初执行的,因此被注入的对象在使用之前,会被完全初始化,这也是构造方法注入的优点之一。
通用性更好
可以适用于任何环境,无论是 IoC框架 还是 非IoC框架
1.没有属性注入简单
2.是构造方法注入,无法解决循环依赖的问题