网站地图 百度,一鸣东莞网站建设公司,衡水专业网站建设公司,wordpress搭建超详细本系列共涉及4个框架#xff1a;Sping,SpringBoot,Spring MVC,Mybatis。
博客涉及框架的重要知识点#xff0c;根据序号学习即可。
有什么不懂的都可以问我#xff0c;看到消息会回复的#xff0c;可能会不及时#xff0c;请见谅#xff01;#xff01; 目录
本系列共…本系列共涉及4个框架Sping,SpringBoot,Spring MVC,Mybatis。
博客涉及框架的重要知识点根据序号学习即可。
有什么不懂的都可以问我看到消息会回复的可能会不及时请见谅 目录
本系列共涉及4个框架Sping,SpringBoot,Spring MVC,Mybatis。
博客涉及框架的重要知识点根据序号学习即可。
1、前言
1.1 Spring具体概念
1.2 什么是容器呢
1.3 什么是IoC
2、IoC详解
2.1 什么是IoC
2.2 IoC有什么作用
2.3 IoC有什么优势
2.4 IoC的使用
2.5 Bean的存储【非常重要一定要好好理解】
2.5.1 Controller控制器存储
2.5.2 Service服务存储
2.5.3 Repository仓库存储
2.5.4 Component 组件存储
2.5.5 Configuration配置存储
2.5.6 Bean 【方法注解---唯一的】
2.6 注解之间的关系
3、DI详解
3.1 什么是DI
3.2 DI与IoC的联系
3.3 DI的使用
3.4 依赖注入的三种方式
3.4.1 属性注入
3.4.2 构造方法注入
3.4.3 Setter注入(设值注入)
3.5 三种注入的优缺点
3.6 Autowired存在的问题 1、前言
1.1 Spring具体概念
之前的文章谈及到什么是Spring但是只给了一个抽象的定义。目前我们知道Spring是一个开源的框架它让我们的开发更加简单也支持广泛的应用场景有着活跃而庞大的社区这也是Spring长久不衰的原因。由于对Spring有着模糊的了解现在给出一个更加具体的概念Spring是一个包含众多工具的Ioc容器【关键词容器Ioc】 1.2 什么是容器呢
容器是用来容纳某种物品的装置。其实在开发圈子容器这个词已经用得泛滥了。
之前我们遇到过什么容器呢
List/Map——数据存储容器
Tomcat——web容器 1.3 什么是IoC
Ioc是Spring的核心思想【Spring两大核心思想Ioc与Aop后续会写关于Aop的文章】。
其实IoC在之前将Spring MVC入门的文章已经用过了在类上面添加RestController和Controller注解就是把这个对象交给Spring管理Spring框架启动时就会加载该类把对象交给Spring管理就是IoC思想。 2、IoC详解
2.1 什么是IoC
1IoCInversion of Control控制反转也就是说Spring是一个控制反转的容器。
2什么是控制反转呢也就是控制权反转。什么的控制权发生反转获得依赖对象的过程被反转了也就是说当需要某个对象时传统开发模式中需要自己new创建对象现在不需要再进行创建把创建对象的任务交给容器程序中只需要依赖注入Dependency Injection,DI就可以了。这个容器称为IoC容器。Spring是一个IoC容器所以有时Spring也称Spring 容器。 2.2 IoC有什么作用 使用IoC思想是将控制权进行反转简而言之就是不再是使用方对象创建并控制依赖对象了而是把依赖对象注入当前对象中依赖对象的控制权不再由当前类控制了。这样的话即使依赖类发生任何改变当前类是不受影响的这就是典型的控制反转也是IoC的实现思想。 2.3 IoC有什么优势
资源不由使用资源的双方管理而是由不使用资源的第三方管理可以带来一下好处
1资源集中管理IoC容器会帮助我们管理一些资源对象等需要使用时直接从IoC容器中去取
2同时在创建实例的时候不需要了解其中的细节降低了使用资源双方的依赖程度以达软件设计原则中的“低耦合”
Spring就是一种IoC容器帮助我们管理资源 2.4 IoC的使用
1既然Spring是一个IoC控制反转容器那么作为容器它的基本功能就是存和取
2Spring容器管理的主要是对象我们称这些对象为“Bean”。我们把这些“Bean”交给Spring管理由Spring来负责对象的创建和销毁我们程序只需要告诉Spring哪些需要存以及哪些需要从Spring中取出来。Spring创建及管理对象就是Bean的存储【非常重要】 2.5 Bean的存储【非常重要一定要好好理解】
要把某个对象交给IoC容器管理需要在类之前加上注解Component而Spring框架为了更好的服务web应用程序提供了更丰富的注解。
共有两类注解类型可以使用
1、类注解Controller、Service、Repository、Component、Configuration
2、方法注解Bean
2.5.1 Controller控制器存储
1使用Controller存储Bean的代码如下
Controller
public class UserController {public void sayHi(){System.out.println(hi,UserController);}
}如何观察这个对象已经存在Spring容器当中了呢
接下来学习如何从Spring容器中获取对象
SpringBootApplication
public class DemoApplication {public static void main(String[] args) {//获取Spring上下文ApplicationContext contextSpringApplication.run(DemoApplication.class,args);//从Spring上下文中获取对象UserController userControllercontext.getBean(UserController.class);//使用对象userController.sayHi();}
} ApplicationContext翻译过来就是Spring上下文。因为对象都交给Spring管理了所以获取对象要从Spring中取那么就需要先得到Spring上下文。当前这个上下文是指当前的运行环境也可以看做是一个容器容器里面存了很多内容这个内容是当前的运行环境。
2Bean命名约定
程序人员不需要为bean指定名称就是说如果没有显式的提供名称Spring容器会为bean生成唯一的名称。
命名约定使用Java标准约定作为实例字段名也就是说bean名称使用小驼峰的形式比如类名为UserController的Bean的名称为userController
当然也会有一些特殊情况就是当多个字符并且第一个和第二个字母都是大写时将保留原始大小写。比如类名为UController的Bean的名称为UController
3获取Bean的其他方式
如果Spring容器中同一个类型存在多个Bean的话怎么获取呢ApplicationContext也提供了其他获取Bean的方式ApplicationContext获取Bean对象的功能是父类BeanFactory提供的功能
SpringBootApplication
public class SpringIocApplication {public static void main(String[] args) {//获取Spring上下文ApplicationContext contextSpringApplication.run(DemoApplication.class,args);//根据bean的类型从上下文中获取对象UserController userController1context.getBean(UserController.class);//根据bean的名字从上下文中获取对象UserController userController2(UserController) context.getBean(userController);//根据bean的类型名字从上下文中获取对象UserController userController3context.getBean(userController, UserController.class);System.out.println(userController1);System.out.println(userController2);System.out.println(userController3);}
} 地址都一样说明是同一个对象
2.5.2 Service服务存储
使用Service存储Bean的代码如下
Service
public class UserService {public void sayHi(){System.out.println(hi,UserService);}
}
获取bean的代码
SpringBootApplication
public class SpringIocApplication {public static void main(String[] args) {//获取Spring上下文ApplicationContext contextSpringApplication.run(DemoApplication.class);//从上下文中获取对象UserService userServicercontext.getBean(UserService.class);//使用对象userService.sayHi();}
} 2.5.3 Repository仓库存储
使用Repository存储Bean的代码如下
Repository //将对象存储到Spring中
public class UserRepository {public void say(){System.out.println(hi,UserRepository);}
}
获取bean的代码
SpringBootApplication
public class DemoApplication {public static void main(String[] args) {//获取Spring上下文ApplicationContext contextSpringApplication.run(DemoApplication.class,args);//从Spring上下文中获取对象UserRepository userRepositorycontext.getBean(UserRepository.class);//使用对象userRepository.sayHi();}
}2.5.4 Component 组件存储
使用Component存储Bean的代码如下
Component
public class UserComponent {public void sayHi(){System.out.println(hi,UserComponent);}
}获取bean的代码
SpringBootApplication
public class DemoApplication {public static void main(String[] args) {//获取Spring上下文ApplicationContext contextSpringApplication.run(DemoApplication.class,args);//从Spring上下文中获取对象UserComponent userComponentcontext.getBean(UserComponent.class);//使用对象userComponent.sayHi();}
}2.5.5 Configuration配置存储
使用Configuration存储Bean的代码如下
Configuration
public class UserConfiguration {public void sayHi(){System.out.println(hi, UserConfiguration);}
}获取bean的代码
SpringBootApplication
public class DemoApplication {public static void main(String[] args) {//获取Spring上下文ApplicationContext contextSpringApplication.run(DemoApplication.class,args);//从Spring上下文中获取对象UserConfiguration userConfigurationcontext.getBean( UserConfiguration .class);//使用对象userConfiguration.sayHi();}
}2.5.6 Bean 【方法注解---唯一的】
在某些外部包的类无法使用类注解以及某些类需要多个对象这个时候需要使用方法注解Bean
1方法注解需要配合类注解使用
import lombok.Data;Data
public class User {private String name;private int age;
}import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;Component
public class BeanConfig {Beanpublic User user(){User usernew User();user.setName(zhangsan);user.setAge(18);return user;}
}import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;SpringBootApplication
public class DemoApplication {public static void main(String[] args) {//获取Spring上下文ApplicationContext contextSpringApplication.run(DemoApplication.class,args);//从Spring上下文中获取对象User usercontext.getBean(User.class);//使用对象System.out.println(user);}
}2定义多个对象
①根据类型获取user时报错显示期望只有一个匹配却发现了两个user1和user2
Component
public class BeanConfig {Beanpublic User user1(){User usernew User();user.setName(zhangsan);user.setAge(18);return user;}Beanpublic User user2(){User usernew User();user.setName(lisi);user.setAge(17);return user;}
}import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;SpringBootApplication
public class DemoApplication {public static void main(String[] args) {//获取Spring上下文ApplicationContext contextSpringApplication.run(DemoApplication.class,args);//从Spring上下文中获取对象User usercontext.getBean(User.class);//使用对象System.out.println(user);}
}②根据名称来获取bean对象
SpringBootApplication
public class DemoApplication {public static void main(String[] args) {//获取Spring上下文ApplicationContext contextSpringApplication.run(DemoApplication.class,args);//从Spring上下文中获取对象User user1 (User) context.getBean(user1);User user2 (User) context.getBean(user2);//使用对象System.out.println(user1);System.out.println(user2);}
} 3重命名Bean
可以通过设置name属性给Bean对象进行重命名。此时我们使用u1就可以获取到User对象了
Component
public class BeanConfig {Bean(name {u1,user1})public User user1(){User usernew User();user.setName(zhangsan);user.setAge(18);return user;}
}
SpringBootApplication
public class DemoApplication {public static void main(String[] args) {//获取Spring上下文ApplicationContext contextSpringApplication.run(DemoApplication.class,args);//从Spring上下文中获取对象User u1 (User) context.getBean(u1);//使用对象System.out.println(u1);}
}2.6 注解之间的关系
1为什么有这么多类注解
这个也是和应用分层相呼应的让开发人员看到类注解之后就能直接了解当前类的用途。
Controller控制层接受请求对请求进行处理并进行响应
Service业务逻辑层处理具体的业务逻辑
Repository数据访问层也称辞旧层负责数据访问操作
Configuration配置层。处理项目中的一些配置信息。 2类注解之间的关系
查看Controller/Service/Repository/Configutation 等注解的源码发现这些注解里面都有一个注解Component说明它们本来就是属于Component的子类。Component是一个元注解就是也可注解其他类的注解Controller/Service/Repository/Configutation等这些注解都被称为Component的衍生注解。 3、DI详解
3.1 什么是DI DIDependency Injection依赖注入。容器在运行期间动态的为应用程序提供运行时所依赖的资源称之为依赖注入。
3.2 DI与IoC的联系
1程序运行时需要某个资源此时容器就为其提供这个资源。从这点可以看出依赖注入DI与控制反转IoC是从不同的角度的描述的同一件事就是指通过引入IoC容器利用依赖关系注入的方式实现对象间的解耦。
2IoC是一种思想也是一种“目标”而思想只是一种指导原则最终还是需要有可行的落地方案而DI就是属于具体的实现所以DI是IoC的一种实现
3.3 DI的使用
依赖注入是一个过程是指IoC容器在创建Bean时去提供运行时所依赖的资源而资源指的就是对象。
3.4 依赖注入的三种方式
3.4.1 属性注入
属性注入式使用Autowired实现的将Service类注入到Controller类中
Service类的实现代码
import org.springframework.stereotype.Service;Service
public class UserService {public void sayHi(){System.out.println(hi,UserService);}
}Controller类的实现代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;Controller
public class UserController {//1、属性注入Autowiredprivate UserService userService;public void sayHi(){System.out.println(hi,UserController);userService.sayHi();}
}获取Controller中的sayHi方法
SpringBootApplication
public class DemoApplication {public static void main(String[] args) {//获取Spring上下文ApplicationContext contextSpringApplication.run(DemoApplication.class,args);//从Spring上下文中获取对象UserController userControllercontext.getBean(UserController.class);//使用对象userController.sayHi();}
}3.4.2 构造方法注入
构造方法是在类的构造方法中实现注入的
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;Controller
public class UserController2 {//2、构造方法注入private UserService userService;Autowiredpublic UserController2(UserService userService){this.userServiceuserService;}public void sayHi(){System.out.println(hi,UserController2);userService.sayHi();}
}SpringBootApplication
public class DemoApplication {public static void main(String[] args) {//获取Spring上下文ApplicationContext contextSpringApplication.run(DemoApplication.class,args);//从Spring上下文中获取对象UserController2 userController2context.getBean(UserController2.class);//使用对象userController2.sayHi();}
} PS:如果类只有一个构造方法那么Autowired注解可以省略如果类中又多个构造方法时那么需要添加上Autowired来明确指定到底使用哪个构造方法 3.4.3 Setter注入(设值注入)
Setter注入和属性的setter方法实现类似只不过在设置set方法的时候加上Autowired注解
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;Controller
public class UserController3 {//2、Setter注入private UserService userService;Autowiredpublic void setUserController3(UserService userService){this.userServiceuserService;}public void sayHi(){System.out.println(hi,UserController3);userService.sayHi();}
}SpringBootApplication
public class DemoApplication {public static void main(String[] args) {//获取Spring上下文ApplicationContext contextSpringApplication.run(DemoApplication.class,args);//从Spring上下文中获取对象UserController3 userController3context.getBean(UserController3.class);//使用对象userController3.sayHi();}
} 3.5 三种注入的优缺点 1属性注入
优点简洁使用方便
缺点只能用于IoC容器不能注入一个final修饰的属性
2构造方法
优点可以注入final修饰的属性注入的对象不会被修改依赖对象在使用前一定会被完全初始化因为依赖是在类的构造方法中执行的而构造方法是在类的加载阶段就会执行的方法通用性好构造方法是JDK支持的所以更换任何框架也是适用的。
缺点注入多个对象时代码会比较繁琐
3setter注入
优点方便在类的实例之后重新对该对象进行配置或者注入
缺点不能注入一个final修饰的属性注入对象可能会被改变因为setter方法可能会被多洗调用就会用被修改的风险
3.6 Autowired存在的问题
1同一类型存在多个bean时使用Autowired会报错。报错的原因是非唯一的Bean对象。上面已经出现过了
2解决方法使用以下注解
Primary、Qualifier、Resource
①使用Primary注解当存在多个相同类型的Bean注入时加上Primary注解用来确定默认的实现
Component
public class BeanConfig {Primary //指定该bean为默认的beanBeanpublic User user1(){User usernew User();user.setName(zhangsan);user.setAge(18);return user;}Beanpublic User user2(){User usernew User();user.setName(lisi);user.setAge(17);return user;}
}②使用Qualifier注解指定当前要注入的bean对象。在Qualifier的value属性中指定注入的bean的名称【Qualifier注解不可以单独使用必须配合Autowired使用】
Controller
public class UserController {Qualifier(user1) //指定bean的名称Autowiredprivate User user;public void sayHi(){System.out.println(hi,UserController);System.out.println(user);}
}
③使用Resource注解是按照bean的名称进行注入。通过name属性指定要注入的bean的名称
Controller
public class UserController {Resource(name user1)private User user;public void sayHi(){System.out.println(hi,UserController);System.out.println(user);}
}