目录
①从Maven中央仓库获取spring-context和spring-beans的依赖,将依赖引入到pom.xml中
②配置扫描路径
③添加注解存储Bean对象(可以使用5大类注解和方法注解)
类注解(写在类上,作用于类上)
@Controller:类标记为控制器
@Service
@Repository
@Component
@Configuration
为什么需要这么多注解?
类注解之间的关系 (除了@Component注解以外的注解,都是基于@Component来实现的。也就是说,@Component是上述所有注解的父类。)
方法注解(作用在方法上的注解) @Bean
为什么不直接加@Bean注解,还需要加类注解?
总结@Bean注解的使用规则:
④从Spring获取Bean对象(对象装配/对象注入)
对象注入的三种方式:
1、属性注入 (@Autowired)
2、构造方法注入 (官方推荐写法)
3、Setter注入
@Resource注解以及它和@Autowired的区别
1、提供方不同
2、支持的注入方式有不同
3、支持的参数不同
属性注入、构造方法注入、Setter注入三种方式获取bean的区别
①从Maven中央仓库获取spring-context和spring-beans的依赖,将依赖引入到pom.xml中
如下配置:
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.24</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.3.24</version>
</dependency>
</dependencies>
②配置扫描路径
找到之前保存在Gitee的相关配置代码:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:content="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">
<!-- 配置 Spring 扫描的根路径(此根路径下的所有 Spring 存对象的注解才能生效) -->
<content:component-scan base-package="com.demo.spring.beans"></content:component-scan>
</beans>
在resources文件中配置spring-config.xml文件并复制以上内容 (注意:配置扫描根路径需要更改为和自己的一致)
③添加注解存储Bean对象(可以使用5大类注解和方法注解)
1: 使用 5 大类注解实现:
@Controller[控制器]
,@Service[服务]
,@Repository[仓库]
,@Configuration[配置]
,Component[组件]
2: 通过方法注解:
@Bean方法
类注解(写在类上,作用于类上)
@Controller:类标记为控制器
控制器:三层架构当中的Controller对应的类。
@Controller注解当中传入的参数,就是这一个类对象的名称。
package com.demo.spring.beans;
import org.springframework.stereotype.Controller;
@Controller("Student")
public class Student {
public void sayHi(){
System.out.println("Hi Student");
}
}
需要注意的是:如果我们在@Controller注解中传入参数了,那么在使用的时候就要按照这个参数的名称来:
如果不一样就会得不到Bean对象:
并且,如果没有给@Controller传入参数的话,默认情况下是小驼峰命名(除了类名是开头两个字母都是大写的情况,如SUser,那么默认也是这个名字)
上述原因还是因为Spring的源码规定的:
在源码中找到这两个方法:
@Service
作用与Controller一样,用于标注"业务逻辑层"的对象。
@Repository
作用与Controller一样,用于标注"持久层"的对象
@Component
不属于前面的任意3层,那么这个注解就可以认为是一个"工具"。
@Configuration
作用与Controller一样,用于标注"配置类"。
以上的注解作用都一样,这里就不一一演示了。
为什么需要这么多注解?
这是让代码的可读性更高,能够让程序员能够直观的判断当前类的用途 。
一般软件开发分四个层次:
@Controller:表示的是业务逻辑层;
@Servie:服务层;
@Repository:持久层;
@Configuration:配置层;
上述的@Component不在这四层之内。
类注解之间的关系 (除了@Component注解以外的注解,都是基于@Component来实现的。也就是说,@Component是上述所有注解的父类。)
如@Controller:
方法注解(作用在方法上的注解) @Bean
先重新创建一个User类:
package com.demo.spring.beans;
public class User {
private int Id;
private String name;
public int getId() {
return Id;
}
public void setId(int id) {
Id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"Id=" + Id +
", name='" + name + '\'' +
'}';
}
}
再创建一个UserBeans:
1、要在类上再加一个5大类注解之一
2、在方法中加Bean注解
为什么不直接加@Bean注解,还需要加类注解?
为了提高效率,当我们添加了5大类注解的时候,Spring就会去扫描这些注解的类,可以大大缩减扫描的范围,然后扫描被@Bean注解的方法。
package com.demo.spring.beans;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;
@Controller
public class UserBeans {
@Bean//方法返回的对象存储在Spring容器
public User user(){
//创建User对象
User user=new User();
//设置属性
user.setId(1);
user.setName("张三");
//返回对象
return user;
}
}
还可以指定返回对象的名称(指定之后原对象名称不可用)
@Bean(name = {"userInfo","user2"})
public User user(){
//创建User对象
User user=new User();
//设置属性
user.setId(1);
user.setName("张三");
//返回对象
return user;
}
获取User对象
import com.demo.spring.beans.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
User user= context.getBean("userInfo", User.class);
System.out.println(user.toString());
}
}
注意:指定返回对象的名称后不能用原来的对象名称,比如上述的只能使用userInfo和user2,而不能使用user:
总结@Bean注解的使用规则:
1、使用@Bean注解的时候要和5大类注解一起使用,这样才能把方法的返回值注入到IoC容器中
2、如果没有指定bean的name属性,默认为方法名,一旦指定就不能用方法名,一个bean可以指定多个name
3、使用@Bean注解了多个方法的时候,并且是相同类型的bean的时候,一定要使用ID+类名的方式使用getBean()方法,否则会出现报错
④从Spring获取Bean对象(对象装配/对象注入)
对象注入的三种方式:
1、属性注入
2、构造方法注入
3、Setter注入
1、属性注入 (@Autowired)
属性注入:把需要获取的对象作为类的属性
如下面把Service类注入到Controllerl类当中:
Service类:
package com.demo.spring.beans;
import org.springframework.stereotype.Service;
@Service
public class UserService {
public void sayHi(){
System.out.println("Hi UserService");
}
}
Controller类:
package com.demo.spring.beans;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
@Autowired
private UserService userService;
public void sayHi(){
userService.sayHi();
}
}
启动类:
import com.demo.spring.beans.UserController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App2 {
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
UserController userController= context.getBean(UserController.class);
userController.sayHi();
}
}
2、构造方法注入 (官方推荐写法)
构造方法注入就是在类的构造方法中实现注入 :
package com.demo.spring.beans;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController2 {
private UserService userService;
//在构造方法上加@Autowired注解
@Autowired
public UserController2(UserService userService){
this.userService=userService;
}
public void sayHi(){
userService.sayHi();
}
}
App启动类:
import com.demo.spring.beans.UserController2;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App3 {
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
UserController2 userController2=context.getBean("userController2", UserController2.class);
userController2.sayHi();
}
}
注意:如果只有一个构造方法的话,上面的@Autowired注解可以省略,官方是这样设定的,如果有多个就不能省略的,并且@Autowired注解只能在一个构造方法上。
3、Setter注入
Setter 注⼊和属性的 Setter ⽅法实现类似,只不过在设置 set ⽅法的时候需要加上@Autowired注解
package com.demo.spring.beans;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController3 {
private UserService userService;
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
public void sayHi(){
userService.sayHi();
}
}
App启动类:
import com.demo.spring.beans.UserController3;
import com.demo.spring.beans.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App4 {
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
UserController3 userController3=context.getBean("userController3",UserController3.class);
userController3.sayHi();
}
}
@Resource注解以及它和@Autowired的区别
@Resource注解和@Autowired注解的作用相似,但是它们还是有些不同的。(一般还是使用@Autowired)
1、提供方不同
@Resource是jdk提供的注解,而@Autowired是Spring提供的
2、支持的注入方式有不同
@Autowired支持以上3种注入方式,而@Resource不支持构造方法注入
3、支持的参数不同
@Resource支持更多的参数设置,比如 name,type 设置,而@Autowired只支持required参数设置
属性注入、构造方法注入、Setter注入三种方式获取bean的区别
①属性注入,简单易用,但是只限于在IoC容器中使用。同时使用属性注入的时候如果这个属性对应的bean不在容器中,属性注入的写法就会失效。
②构造方法注入,安全性升级,有良好的通用性,支持非Ioc容器。它保证了使用这个类的其他方法之前,属性已经被注入了(构造方法的缘故),避免了NullPointException。
③Setter方法注入,写法复杂一点,支持非IoC容器,同时通用性好,适合单元性测试。程序猿可以通过调用setter方法进行不同参数的传入