目录
一、创建项目并且配置扫描路径
1.创建maven项目并且添加依赖
2.创建com.java.demo包并且添加Bean对象User
3.配置扫描路径
二、更加简单的存储Bean对象
使用类注解存储Bean对象
使用方法注解存储bean对象(@Bean)
三、更加简单的读取Bean对象(依赖注入)
1.属性注入
2. Setter注入
3. 构造方法注入
四、总结(注意事项)
1. 使用类注解的注意事项
通过类注解(5大类)实现Bean对象的存储
关于类注解默认命名方式
2. 使用方法注解的注意事项
使用方法注解时要配合五大类注解才成功使用
使用方法注解的命名规则
重命名bean方式
多个Bean使用相同名称
3.Spring 依赖注入各有什么优缺点?
(一定要做的步骤)
在pom.xml中添加以下依赖
org.springframework
spring-context
5.2.3.RELEASE
org.springframework
spring-beans
5.2.3.RELEASE
对象必须放在被扫描到的目录里面。
给前面的User类加上注解:(只写了使用@Controller注解)
@Controller()
public class User {
public void sayHi(){
System.out.println("hello");
}
}
读取:
public class App {
public static void main(String[] args) {
//1.得到容器对象
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
//2.得到Bean对象
User user = context.getBean("user",User.class);
//3.使用Bean对象
user.sayHi();
}
}
类注解时添加到某个类上面的,而方法注解时放到某个方法上面。
首先创建一个实体类ArticleInfo(这个看看就行,不了解没事)
package com.java.demo.model;
import java.time.LocalDateTime;
public class ArticleInfo {
private int aid;
private String title;
private String content;
private LocalDateTime createTime;
@Override
public String toString() {
return "ArticleInfo{" +
"aid=" + aid +
", title='" + title + '\'' +
", content='" + content + '\'' +
", createTime=" + createTime +
'}';
}
public int getAid() {
return aid;
}
public void setAid(int aid) {
this.aid = aid;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
}
然后使用方法中注解将当前方法返回的对象存储到IoC中:
package com.java.demo;
@Component
public class Articles {
@Bean //将当前方法返回的对象存储到IoC
public ArticleInfo articleInfo(){
ArticleInfo articleInfo = new ArticleInfo();
articleInfo.setAid(1);
articleInfo.setTitle("hellp");
articleInfo.setContent("helloword");
articleInfo.setCreateTime(LocalDateTime.now());
return articleInfo;
}
}
读取存储的对象:
public class App {
public static void main(String[] args) {
//1.得到容器对象
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
//2.得到Bean对象
//User user = context.getBean("user",User.class);
ArticleInfo articleInfo = context.getBean("articleInfo",ArticleInfo.class);
//3.使用Bean对象
//user.sayHi();
System.out.println(articleInfo.toString());
}
}
获取Bean对象也叫做对象装配,把对象取出放到某个类中,也叫做对象注入。
对象注入一共有3种实现方式:属性注入、构造方法注入、Setter注入。
首先创建一个UserRepository类
@Repository
public class UserRepository {
public int add(){
System.out.println("Do UserRepository add mathod");
return 1;
}
}
@Autowired属性注入 /依赖注入流程:
首先根据getType(从容器中)获取对象,
如果只获取了一个对象,那么直接将此对象直接注入到当前属性上;
如果获取到多个对象,才会使用getName根据名称进行匹配。
如果只获取了一个对象,下面的名称(userRepository)取什么都可以,这个名称就是一个辅助项;
@Service
public class UserService {
//1.属性注入
@Autowired //从spring当中取到UserRepository并把它设置给当前的变量
private UserRepository userRepository;//名称可以随意取,这里的名称就不会被约束了
public int add(){
System.out.println("Do UserService add method");
return userRepository.add();
}
}
如果获取到多个对象,才会使用getName根据名称进行匹配。
创建一个实体类User(不懂不用管,只是为了供后面的示例代码使用)
public class User {
private String name;
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
使用方法注解,将对象存储到容器中:
@Component
public class Users {
@Bean("user1")
public User user1() {
User user = new User();
user.setName("张三");
return user;
}
@Bean("user2")
public User user2(){
User user = new User();
user.setName("李四");
return user;
}
}
使用属性注入取出对象:
@Service
public class UserService2 {
//属性注入
@Autowired
@Qualifier("user1") //指定取出的是user1
private User user;
public void sayHi(){
System.out.println(user.toString());
}
}
创建测试类:
class UserService2Test {
@Test
void add() {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
UserService2 userService2 = context.getBean("userService2",UserService2.class);
userService2.sayHi();
}
}
@Service
public class UserService3 {
private UserRepository userRepository;
@Autowired //不能省略
//使用setter的方式将对象注入
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void sayHi(){
System.out.println("Do UserService3 sayHi");
userRepository.add();
}
}
public class UserService4 {
private UserRepository userRepository;
@Autowired
public UserService4(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void sayHi(){
System.out.println("hello ,UserService4");
userRepository.add();
}
}
关于三种依赖注入方式的优缺点,参考博客:
Spring的一些基本概念_️藿香正气水的博客-CSDN博客
@Controller【控制器】:校验参数的合法性(安检系统)
@Service【服务】业务组装(客服中心)
@Repository【数据持久层】业的业务处理(实际办理业务)
@Component【组件】工具类,实现业务中通用的功能(基础工具)
@Configuration【配置】配置层(针对当前做出一些设置)
阿里巴巴java开发手册工程结构:
Web层就相当于Controller控制层。
以下时user就是一种注解命名“
JDK中的命名方式其实并不全是上面这样的,主要的命名方式如下:
1. 当类名的首字母大写,第二个字母小写时,比如User,UserService等这种形式的类名,那么类注解就会默认使用首字母小写的方式命名,比如类名时UserService,那么类注解命名就是userService;
2.当类名的首字母大写,比如UConfig,UService等这种格式的类名,类注解就会默认使用原类名,也就是比如类名时UConfig,那么类注解命名也是UConfig。
和类注解不同,使用方法注解时,默认情况下,获取类的命名必须和方法名对应一致。也就是上图中的地方需要一一对应。
@Bean支持指定多个名称
方式1:@bean("a"),也可以使用多个名称来设置一个对象@bean({"a",""b})
方式2:@bean(name = "a") ,也可以使用多个名称来设置一个对象@bean(name={"a","b"})
方式3:@bean(value = "a" ),也可以使用多个名称来设置一个对象@bean(value={"a","b"})
当用了方法注解重命名以后,再次使用前面的默认使用方法名获取bean对象的方式就不能使用了。
如果多个Bean使用多个名称,那么程序执行时不会报错,但是第一个Bean之后的队形不会被存放到容器中,也就是只有在第一次创建Bean的时候会将对称和Bean关联起来,后续再有相同名称的Bean存储的时候,容器会自动忽略。
属性注入
优点:使用简单
缺点:
无法注入finali修饰的变量
首先final的特征(两种):被修饰的变量需要赋值;在构造方法里面需要进行赋值。
通用性问题:只适用于IoC容器。
设计原则问题:更容易违背单一设计问题,因为使用起来比较简单。
Setter注入
优点:更符合单一设计原则。因为Setter只有Set一个属性。
缺点:
无法注入一个final修饰的变量
setter注入的对象是可以被需改的
构造方法注入
优点:
可以注入一个final修饰的变量
注入的对象不会被改变,因为构造方法只会被加载一次
构造方法注入可以保证被注入的对象完全初始化
构造方法注入通用性更好
缺点:
写法比属性注入复杂
无法解决循环依赖的问题