目录
ApplicationContext VS BeanFactory
使用Maven创建Spring项目
1.创建Spring项目
1.1 创建普通的Maven项目
1.2 添加Spring框架(spring-context、spring-beans)
在pom.xml中添加依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
</dependencies>
当出现如图所示的包,说明已经从一个Maven项目变成了一个Spring项目。
1.3添加启动类
在java文件夹下创建启动类,包含main方法即可(目的:一个启动类,为了测试Spring的存对象去对象功能)
public class Application {
public static void main(String[] args) {
}
}
这个main方法启动,Spring框架也就启动了,因为此类是放在当前框架中。
2.存储Bean对象
2.1创建Bean
Bean其实就是java中的一个普通对象,如下:
/**
* 创建一个方法,打印传递的名称
*/
public class UserBean {
public void hello(String name){
System.out.println(name);
}
}
2.2 将Bean注册到容器中
在创建好的项⽬中添加 Spring 配置⽂件 spring-config.xml,将此⽂件放到 resources 的根⽬录下。
再将 User 对象注册到 Spring 中就可以,具体操作是在spring-config.xml中添加配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<beans>
<bean id="user" class="model.UserBean"></bean>
</beans>
</beans>
3.获取并使用Bean对象
分为以下三步:
public class Application {
public static void main(String[] args) {
// 1.获取Spring的上下文对象
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
// 2.从Spring上下文中获取到业务对象【通过Bean的id来获取到Bean对象】
UserBean user = (UserBean) context.getBean("user");
// 3.使用业务对象
user.printName("java");
}
}
如果取多个Bean,就重复2、3步骤。
3.1获取Spring对象的方法(如下三种):
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
BeanFactory beanFactory =
new ClassPathXmlApplicationContext("spring-config.xml");
BeanFactory beanFactory1 =
new XmlBeanFactory(new ClassPathResource("spring-config.xml"));
ApplicationContext VS BeanFactory
- 从继承功能方面来说:ApplicationContext是BeanFactory的子类,BeanFactory所有的功能ApplicationContext也是拥有的,除此之外ApplicationContext还有其他BeanFactory没有的功能,例如,还添加了对国际化的支持、资源访问支持、以及事件传播等方面的支持。
- 从性能方面来说:ApplicationContext是一次性加载并初始化所有的对象(第一次启动时慢,但当后续的执行时就比较快),而BeanFactory是需要用到哪个才加载哪个,(更加轻量,占用的资源更少,比较快,但是后续的执行可能会比较慢)。
3.2 获取Bean的三种方法
方式一:通过Bean的id来获取
缺点:需要类型强转
public class Application {
public static void main(String[] args) {
// 1.获取Spring的上下文对象
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
// 2.从Spring上下文中获取到业务对象
// 【方式一:通过Bean的 id 来获取到Bean对象】
UserBean user = (UserBean) context.getBean("user");
// 3.使用业务对象
user.printName("java");
}
}
方式二:通过对象类型获取
优点:不需要类型强转
缺点:对于多个对象同种类型,会报错
public class Application {
public static void main(String[] args) {
// 1.获取Spring的上下文对象
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
// 2.从Spring上下文中获取到业务对象
// 【方式二:通过 对象类型 获取到Bean对象】
UserBean user = context.getBean(UserBean.class);
// 3.使用业务对象
user.printName("java");
}
}
方式三:通过 id+对象类型
优点:不需要类型转换,某个类型被重复时,不会报错。
public class Application {
public static void main(String[] args) {
// 1.获取Spring的上下文对象
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
// 2.从Spring上下文中获取到业务对象
// 【方式三:通过 id+对象类型 获取到Bean对象】
UserBean user = context.getBean("user", UserBean.class);
// 3.使用业务对象
user.printName("java");
}
}
方式三较方式二的优点在于:
当一个类型被重复注册到spring-config.xml中时,使用方法二就会报错。
总结流程图:
Spring更简单的读取和存储对象
1.存储Bean对象
之前是在spring-config.xml中添加一行bean的注册内容,现在通过注解的方式。
1.1 配置扫描路径
注:要想将对象存储进Spring需要配置存储对象扫描包的路径,只有被配置过的包下的所有类,添加了注解才能被正确识别并保存到Spring中。(修改成自己的base-package)
<?xml version="1.0" encoding="UTF-8"?>
<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.sunnan">
</content:component-scan>
</beans>
1.2添加注解存储Bean对象
想要将对象存储进Spring中,有两种注解方式:
类注解:@Controller (控制器) @Service (业务逻辑层) @Repository(数据持久层) @Component(组件类) @Configuration(配置类)
方法注解:@Bean
1.2.1 @Controller(控制器)示例
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
public void sayHi(String name){
System.out.println("hi,controller: " + name);
}
}
1.2.2 @Service(服务存储)示例
import org.springframework.stereotype.Service;
@Service
public class UserService {
public void sayHi(String name){
System.out.println("hi,service:" + name);
}
}
1.2.3@repository(仓库存储)
import org.springframework.stereotype.Repository;
@Repository
public class UserRepository {
public void sayHi(String name){
System.out.println("hi,repository:" + name);
}
}
1.2.4Configuration(配置存储)
import org.springframework.context.annotation.Configuration;
@Configuration
public class UserConfiguration {
public void sayHi(String name){
System.out.println("hi,configuration:" + name);
}
}
1.2.5Component(组件存储)
import org.springframework.stereotype.Component;
@Component
public class UserComponent {
public void sayHi(String name){
System.out.println("hi,component:" + name);
}
}
/**
* Spring启动类 为了方便演示功能才创建的
*/
public class App {
public static void main(String[] args) {
// 1.先获取Spring的上下文
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
// 2.从Spring中获得存入的对象(id默认的规则使将存入的类首字母小写)
UserController userController = context.getBean("userController", UserController.class);
// 3.使用
userController.sayHi("controller");
UserService userService = context.getBean("userService", UserService.class);
userService.sayHi("service");
UserRepository userRepository = context.getBean("userRepository", UserRepository.class);
userRepository.sayHi("repo");
UserConfiguration userConfiguration = context.getBean("userConfiguration", UserConfiguration.class);
userConfiguration.sayHi("config");
UserComponent userComponent = context.getBean("userComponent", UserComponent.class);
userComponent.sayHi("component");
}
}
1.2.6使用方法注解 @Bean
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Component
public class UserBean {
@Bean
public User user1(){
User user = new User();
user.setId(1);
user.setName("张三");
user.setAge(18);
return user;
}
}
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
User user1 = context.getBean("user1", User.class);
System.out.println(user1);
}
}
注:方法注解和类注解是不一样的,方法注解必须配合类注解才能加载进Spring。
Spring默认情况下是类扫描。
2.从Spring中获取Bean对象
获取Bean对象也叫对象装配,是把对象取出来放到某个类中,有时候也叫对象注入。
对象注入实现方法有三种:
- 属性注入
- 构造方法注入
- Setter注入
2.1属性注入
属性注⼊是使⽤ @Autowired 实现的,
将 Service 类注⼊到 Controller 类中。
Service 类的实现代码如下:
import com.sunnan.model.User;
import org.springframework.stereotype.Service;
@Service
public class UserService {
/**
* 根据用户id 获取用户对象
* @param id
* @return
*/
public User findUserById(int id){
// 伪代码查询数据库,返回用户对象
User user = new User();
if(id == 1){
user.setId(1);
user.setName("张三");
user.setAge(18);
}else{
user.setId(2);
user.setName("李四");
user.setAge(19);
}
return user;
}
}
Conrroller类实现代码如下:
通过属性注入
import com.sunnan.model.User;
import com.sunnan.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
// 1.属性注册,从Spring中获取一个对象,并注入到当前类
@Autowired
private UserService userService;
// 2.上述注入已经获取到了userService,下面创建方法开始使用
// 根据用户id 查询用户对象
public User findUserById(Integer id){
if(null == id){
// 无效参数时,返回一个空的User对象
return new User();
}
return userService.findUserById(id);
}
}
public class App {
public static void main(String[] args) {
// 1.先获取Spring的上下文
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
// 2.得到UserController对象
UserController controller = context.getBean("userController",UserController.class);
// 3.根据对象调用findUserById 查询用户信息
User user = controller.findUserById(2);
System.out.println(user);
}
}
通过Setter的方式注入
@Controller
public class UserController2 {
// 1.将UserService方法注入【Setter注入方式】
private UserService userService;
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
// 2.新建一个方法,在方法里调用UserService的查询方法,返回用户对象
public User findUserById(Integer id){
return userService.findUserById(id);
}
}
构造方法注入
@Controller
public class UserController3 {
// 使用构造方法进行对象注入
private UserService userService;
// 给构造方法添加Autowired注解
@Autowired
public UserController3(UserService userService) {
this.userService = userService;
}
public User findUserById(Integer id){
return userService.findUserById(id);
}
}
注:构造方法注入,如果当前类只有一个构造方法,那么@Autowired注解可以被省略,这点和Setter注入是不同的。
2.2 三种注入方式的优缺点
- 属性注⼊的优点是简洁,使⽤⽅便;缺点是只能⽤于 IoC 容器,如果是⾮ IoC 容器不可⽤,并且只 有在使⽤的时候才会出现 NPE(空指针异常)。
- 构造⽅法注⼊是 Spring 推荐的注⼊⽅式,它的缺点是如果有多个注⼊会显得⽐较臃肿,但出现这种 情况你应该考虑⼀下当前类是否符合程序的单⼀职责的设计模式了,它的优点是通⽤性,在使⽤之 前⼀定能把保证注⼊的类不为空。
- Setter ⽅式是 Spring 前期版本推荐的注⼊⽅式,但通⽤性不如构造⽅法,所有 Spring 现版本已经 推荐使⽤构造⽅法注⼊的⽅式来进⾏类注⼊了。
2.3@Resource注入:另一种注入关键字
@Controller
public class UserController {
// 注⼊
@Resource
private UserService userService;
public User getUser(Integer id) {
return userService.getUser(id);
}
}
2.4@Resource @Autowired区别
- 出身不同:@Autowired来自Spring,@Resource来自JDK注解
- 作用范围:@Resource只能作用于属性注解和Setter注解,不能用构造器注入,而@Autowired都可以。
- 功能不同:@Resource可以配合更多的属性进行使用,而@Autowired支持的属性很少,比如@Resource可以配合name属性进行使用,从而完成对象的别名注入。
2.5解决同一类型多个Bean的报错
@Resource(name="")
@Autowired搭配@Qualifier("")使用