> 文章列表 > Spring更简单的读取和存储Bean(基于注解)

Spring更简单的读取和存储Bean(基于注解)

Spring更简单的读取和存储Bean(基于注解)

目录

①从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;}@Overridepublic 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 {@Autowiredprivate 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注解@Autowiredpublic 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;@Autowiredpublic 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方法进行不同参数的传入