Spring5
IOC控制反转
IOC(Inversion of Controller)翻译过来’控制反转’
IOC本质上是一个概念,是一种思想,控制反转就是对对象控制权的转移,SpringIoC容器创建对象,然后将对象的使用权交出去
SpringFramework相关Jar地址: https://repo.spring.io/libs-release-local/org/springframework/spring/
IOC 通俗一点 就是把对象交给spring容器管理 一种思想 指导我们设计出松耦合得程序 提高功能复用
DI 依赖注入 spring容器负责将被依赖对象赋值给成员变量,这相当于为实例对象注入了它所依赖的实例 也就是依赖注入 老版本 就是get set
AOP 切面编程 可用于日志 事务…等场景
基于XML配置
注册Bean
<?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">
<!-- 添加需要被容器管理的内容-->
<bean class="com.wlr.WlrBean" />
</beans>
// 1.IoC容器的初始化操作 调用WlrBean中无参构造器创建对象
ApplicationContext ac =
new ClassPathXmlApplicationContext("applicationContext.xml");
// 2.从容器中获取WlrBean对象
WlrBean wlr = (WlrBean) ac.getBean("wlrBean");
wlr.say();
从容器中获取对象的方式
根据ID
id只能声明一个
根据name
可以声明一个或者多个
<bean class="com.wlr.WlrBean" id="user1,user2,user3" name="u1,u2,u3"/>
id=“user1,user2,user3” 只表示一个
name=“u1,u2,u3” 表示会被拆分为3个name属性【拆分会根据 ‘,’ ‘;’ ’ ’ 空格 】
根据类型
我们可以根据需要获取的对象的类型从容器中获取对象
@Test
public void fun(){
ApplicationContext ac =
new ClassPathXmlApplicationContext("applicationContext.xml");
WlrBean bean = ac.getBean(WlrBean.class);
bean.say();
}
如果同一类型的对象在容器中有多个,如果我们仅仅只是通过类型来查找,那么就会报错
<bean class="com.wlr.WlrBean" id="user1,user2,user3" name="u1 u2 u3"/>
<bean class="com.wlr.WlrBean" id="WlrBea1" name="ub1"/>
在getBean方法中通过组合条件查找
@Test
public void fun(){
ApplicationContext ac =
new ClassPathXmlApplicationContext("applicationContext.xml");
WlrBean bean = ac.getBean("u1",WlrBean.class);
bean.say();
}
还要就是我们可以在 中设置 primary属性为true,那么当同一类型有多个对象时,会优先返回primary属性的对象
BeanFactory和ApplicationContext的区别
从类图结构中我们可以很清晰的看到ApplicationContext具有BeanFactory的所有功能,同时扩展了很多BeanFactory不具备的功能【事件广播,资源加载,web支持等等…】
工厂注入
静态工厂注入
<bean class="com.wlr.factory.StaticFactoryDemo" factory-method="getInstance" id="user"></bean>
动态工厂注入
public WlrBean getInstance(){
return new WlrBean();
}
<!-- 通过动态工厂的方式注入 -->
<bean class="com.wlr.factory.DynamicFactoryDemo" id="dynamicFactoryDemo" ></bean>
<!-- 从工厂对象中获取 需要的对象-->
<bean id="user2" factory-bean="dynamicFactoryDemo" factory-method="getInstance"/>
配置注解
注解名称 | 说明 |
---|---|
@Configuration | 把一个类作为一个IoC容器,它的某个方法头上如果注册了@Bean,就会作为这个Spring容器中的Bean。 |
@ComponentScan | 在配置类上添加 @ComponentScan 注解。该注解默认会扫描该类所在的包下所有的配置类,相当于之前的 context:component-scan |
@Scope | 用于指定scope作用域的(用在类上) |
@Lazy | 表示延迟初始化 |
@Conditional | Spring4开始提供,它的作用是按照一定的条件进行判断,满足条件给容器注册Bean。 |
@Import | 导入外部资源 |
生命周期控制 | @PostConstruct用于指定初始化方法(用在方法上)@PreDestory用于指定销毁方法(用在方法上)@DependsOn:定义Bean初始化及销毁时的顺序 |
扩展:SpringBoot中的ConditionalXXX
@Conditional扩展注解 | 作用(判断是否满足当前指定条件) |
---|---|
@ConditionalOnJava | 系统的Java版本是否符合要全 |
@ConditionalOnBean | 容器中存在指定的Bean |
@ConditionalOnMissingBean | 容器中不存在指定的Bean |
@ConditionalOnExpression | 满足SpEL表达式 |
@ConditionalOnClass | 系统中有指定的类 |
@ConditionalOnMissingClass | 系统中没有指定的类 |
@ConditionalOnSingleCandidate | 容器中只有一个指定的Bean,或者这个Bean是首选Bean |
@ConditionalOnProperty | 系统中指定的属性是否有指定的值 |
@ConditionalOnResource | 类路径下是否存在指定的资源文件 |
@ConditionalOnWebApplication | 当前是Web环境 |
@ConditionalOnNotWebApplication | 当前不是Web环境 |
@ConditionalOnJndi | JNDI存在指定项 |
赋值注解
注解名称 | 说明 |
---|---|
@Component | 泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。 |
@Service | 用于标注业务层组件 |
@Controller | 用于标注控制层组件 |
@Repository | 用于标注数据访问组件,即DAO组件。 |
@Value | 普通数据类型赋值 |
@Autowired | 默认按类型装配,如果我们想使用按名称装配,可以结合@Qualifier注解一起使用 |
@PropertySource | 读取配置文件赋值 |
@Qualifier | 如存在多个实例配合使用 |
@Primary | 自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常 |
@Resource | 默认按名称装配,当找不到与名称匹配的bean才会按类型装配。 |
@Autowired和@Resource的区别
@Autowired:默认只能根据类型来查找,可以结合@Qualifier(“abc”)注解来实现通过name查找
@Resource:默认同样是根据类型来查找,但是提供的有type和name属性类实现不同的查找方式
将类型加入到IoC容器中的方式
1.基于XML文件的方式
2.基于XML文件的方式context:Component-Scan + @Component
3.基于Java配置类@Bean
4.基于Java配置类@ComponentScan + @Component
5.FactoryBean + getObject方法
6.@Import
Bean对象的作用域
作用域 | 说明 |
---|---|
prototype | 每次请求,都是一个新的Bean( java原型模式 ) |
singleton | bean是单例的(Java单例模式) |
request | 在一次请求中,bean的声明周期和request同步 |
session | bean的生命周期和session同步 |
默认的情况是 singleton
@Bean
@Scope("prototype")
public Person person(){
return new Person();
}
@Bean
@Scope("singleton")
public Person person(){
return new Person();
}
AOP前置之代理模式
SpringFramework的核心
IoC[DI]
AOP 面向切面编程
代理对象:增强目标对象
静态代理
直接将代理对象声明出来
定义接口
public interface SomeService {
public String wlr(String wlr);
}
创建目标对象
public class SomeServiceImpl implements SomeService {
@Override
public String wlr(String wlr) {
System.out.println("目标对象执行..." + wlr);
return "wlr";
}
}
创建静态代理类
public class StaticSomeProxy implements SomeService {
private SomeService someService;
public StaticSomeProxy() {
}
public StaticSomeProxy(SomeService someService) {
this.someService = someService;
}
@Override
public String wlr(String wlr) {
System.out.println("目标对象执行之前的操作....");
// 调用目标对象的方法
String res = someService.wlr(wlr);
System.out.println("目标对象执行之后的操作....");
return res.toUpperCase();
}
}
测试
public class test01 {
public static void main(String[] args) {
// 获取目标对象
SomeService someService = new SomeServiceImpl();
// 获取代理对象 增强目标对象
StaticSomeProxy staticSomeProxy = new StaticSomeProxy(someService);
System.out.println(staticSomeProxy.wlr("无聊人"));
}
}
动态代理
JDK动态代理
如果目标实现的有接口 我们就可以使用JDK代理模式
public class test02 {
public static void main(String[] args) {
// 获取目标对象
SomeService someService = new SomeServiceImpl();
// 获取代理对象
SomeService proxy = (SomeService)Proxy.newProxyInstance(
someService.getClass().getClassLoader() // 类加载器
, someService.getClass().getInterfaces() // 目标对象实现的接口数组
, new InvocationHandler() { // InvocationHandler的实现
//当代理对象执行相关方法的时候会执行的逻辑
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("目标方法执行之前....");
// 调用目标对象的方法
String msg = (String) method.invoke(someService, args[0]);
System.out.println("目标方法执行之后....");
return msg.toUpperCase();
}
}
);
System.out.println(proxy.wlr("wlr"));
}
}
CGLIB动态代理
如果目标对象没有实现任何的接口那么我们是使用不了JDK动态代理的 这个时候我们只能使用CGLIB代理 CGLIB的本质其实的代理类继承了目标对象 并重写相关方法
引入CGLIB的依赖
<dependencies>
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
</dependencies>
创建目标对象
public class WlrServiceImpl{
public String wlr(String wlr) {
System.out.println("目标对象执行..." + wlr);
return "wlr";
}
}
创建代理类
public class CglibProxy implements MethodInterceptor {
private WlrServiceImpl target;
public CglibProxy(WlrServiceImpl target) {
this.target = target;
}
//给外界暴露的创建代理对象的方法
public WlrServiceImpl createProxy(){
Enhancer enhancer = new Enhancer();
// 指定父类
enhancer.setSuperclass(WlrServiceImpl.class);
// 指定回调方法
enhancer.setCallback(this);
// 创建对象代理对象
return (WlrServiceImpl) enhancer.create();
}
//需要执行具体的代理方法
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before...");
String msg = (String) method.invoke(target, objects[0]);
System.out.println("after...");
return msg.toUpperCase();
}
}
测试
public class test03 {
public static void main(String[] args) {
// 获取目标对象
WlrServiceImpl target = new WlrServiceImpl();
// 获取代理对象
WlrServiceImpl proxy = new CglibProxy(target).createProxy();
System.out.println(proxy.wlr("wlr"));
}
}
SpringAOP
面向切面编程,就是将交叉业务逻辑封装成切面,利用AOP的功能将切面织入到主业务逻辑中。所谓交叉业务逻辑是指,通用的、与主业务逻辑无关的代码,如安全检查、事务、日志等。若不使用AOP,则会出现代码纠缠,即交叉业务逻辑与主业务逻辑混合在一起。这样,会使主业务逻辑变的混杂不清
术语 | 说明 |
---|---|
切面 | 切面泛指交叉业务逻辑。比如事务处理、日志处理就可以理解为切面。常用的切面有通知与顾问。实际就是对主业务逻辑的一种增强 |
织入 | 织入是指将切面代码插入到目标对象的过程。 |
连接点 | 连接点指切面可以织入的位置。 |
切入点 | 切入点指切面具体织入的位置。 |
通知(Advice) | 通知是切面的一种实现,可以完成简单织入功能(织入功能就是在这里完成的)。通知定义了增强代码切入到目标代码的时间点,是目标方法执行之前执行,还是之后执行等。通知类型不同,切入时间不同。 |
顾问(Advisor) | 顾问是切面的另一种实现,能够将通知以更为复杂的方式织入到目标对象中,是将通知包装为更复杂切面的装配器。 不仅指定了切入时间点,还可以指定具体的切入点 |
AspectJ的使用
<!-- springBoot自带-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.17.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
放开AspectJ
@Configuration
@EnableAspectJAutoProxy // 放开AspectJ的使用
@ComponentScan("com.wlr.aop")
public class JavaConfig {
public static void main(String[] args) {
ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
SomeService bean = ac.getBean(SomeService.class);
bean.wlr("wlr");
}
}
创建切面类
@Aspect // 显示的表明当前类是一个切面类
@Component // 将该对象加载到IoC容器中
public class MyAspectJ01 {
/**
* 要增强目标对象的方法
* 指定目标对象
* 切入点表达式
*/
@Before("execution(* com.wlr.aop.service.impl.*.wlr(..))")
public void aspectMethod01(){
System.out.println("before ....");
}
}
切入点表达式
表达式类型 | 说明 |
---|---|
execution | 定位到目标对象的方法上 |
within | 定位到具体的类型上 |
this | 代理对象的类型 |
target | 目标对象的类型 |
args | 参数的类型 |
@args | 传入的参数有被该注解修饰 |
@within | 类型修饰的注解 |
@annotation | 方法修饰的注解 |
execution表达式
语法: execution([访问权限类型] 返回值类型 [全限定类名] 方法名(参数名) [抛出的异常类型])
符号 | 含有 |
---|---|
* | 0到多个符合 |
… | 方法参数中表示任意个参数,用在报名后表示当前包及其子包 |
+ | 用在类名后表示当前类及其子类,用在接口后表接口及其实现 |
实例:
execution(public * *(. .))
指定切入点为:任意公共方法。
execution(* set *(. .))
指定切入点为:任何一个以“set”开始的方法。
execution(* com.xyz.service.*.*(. .))
指定切入点为:定义在service包里的任意类的任意方法。
execution(* com.xyz.service. .*.*(. .))
指定切入点为:定义在service包或者子包里的任意类的任意方法。“..”出现在类名中时,
后面必须跟“*”,表示包、子包下的所有类。
execution(* *.service.*.*(. .))
指定只有一级包下的serivce子包下所有类(接口)中的所有方法为切入点
execution(* *. .service.*.*(. .))
指定所有包下的serivce子包下所有类(接口)中的所有方法为切入点
切面类例
目标对象
@Service
@WlrAnnotation01
public class SomeServiceImpl implements SomeService {
@Override
public String wlr(String wlr) {
System.out.println("目标对象执行..." + wlr);
return "wlr";
}
}
切面类
@Aspect // 显示的表明当前类是一个切面类
@Component // 将该对象加载到IoC容器中
public class MyAspectJ01 {
//切入点复用
@Pointcut("execution(* com.wlr.aop.service.impl.*.*(..))")
public void pointcut1(){
}
/**
* 要增强目标对象的方法
* 指定目标对象
* 切入点表达式
*/
@Before("pointcut1()")
public void aspectMethod01(){
System.out.println("before ....");
}
/**
* 定位到具体的类型上
*/
@Before("within(com.wlr.aop.service.impl.*)")
public void aspectMethod02(){
System.out.println("before222 ....");
}
/**
* 在AOP中 如果目标对象实现接口 默认使用的是JDK代理模式
* this 指的就是代理对象
* 要使this使用 cglib 代理模式 改动javaConfig 上@EnableAspectJAutoProxy(proxyTargetClass = true)
*/
@Before("this(com.wlr.aop.service.impl.SomeServiceImpl)")
public void aspectMethod03(){
System.out.println("before333 ....");
}
/**
* target 目标对象 com.wlr.aop.service.impl.SomeServiceImpl
*/
@Before("target(com.wlr.aop.service.impl.SomeServiceImpl)")
public void aspectMethod04(){
System.out.println("before444 ....");
}
/**
* 参数的类型
* 结合使用
* @Before("target(com.wlr.aop.service.impl.SomeServiceImpl) && args(String)")
*/
@Before("args(String)")
public void aspectMethod05(){
System.out.println("before555 ....");
}
@Before("@within(com.wlr.aop.annotation.WlrAnnotation01)")
public void aspectMethod06(){
System.out.println("before666 ....");
}
}
注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface WlrAnnotation01 {
}
测试
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true) // 放开AspectJ的使用
@ComponentScan("com.wlr.aop")
public class JavaConfig {
public static void main(String[] args) {
ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
SomeService bean = ac.getBean(SomeService.class);
//SomeServiceImpl bean = ac.getBean(SomeServiceImpl.class);
bean.wlr("wlr");
}
}
通知类型
通知类型 | 说明 |
---|---|
前置通知 | 目标方法执行之前调用 |
后置通知 | 目标方法执行完成之后调用 |
环绕通知 | 目标方法执行前后都会调用方法,且能增强结果 |
异常处理通知 | 目标方法出现异常调用 |
最终通知 | 无论程序执行是否正常,该通知都会执行。类似于try…catch中finally代码块 |
@Aspect
@Component
public class MyAspectJ02 {
/**
* 前置
*/
@Before("execution(* com.wlr.aop.service.impl.*.*(..))")
public void aspectMethod01(){
System.out.println("Before ....");
}
/**
* 后置
*/
@AfterReturning(value = "within(com.wlr.aop.service.impl.*)",returning = "res")
public void aspectMethod02(Object res){
System.out.println("AfterReturning ...." + res);
}
/**
* 环绕
*/
@Around(value = "within(com.wlr.aop.service.impl.*)")
public void aspectMethod03(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("目标前...");
Object[] args = proceedingJoinPoint.getArgs(); //对象的形参
Object proceed = proceedingJoinPoint.proceed();//目标对象方法执行
System.out.println("目标后..." + proceed);
}
/**
* 异常
*/
@AfterThrowing(value = "within(com.wlr.aop.service.impl.*)",throwing = "ex")
public void aspectMethod04(Exception ex) {
System.out.println("AfterThrowing..." + ex);
}
/**
* 最终
*/
@After(value = "within(com.wlr.aop.service.impl.*)")
public void aspectMethod04() {
System.out.println("After...");
}
}
事务的传播行为
Spring中的7个事务传播行为:
事务行为 | 说明 |
---|---|
PROPAGATION_REQUIRED | 支持当前事务,假设当前没有事务。就新建一个事务 |
PROPAGATION_SUPPORTS | 支持当前事务,假设当前没有事务,就以非事务方式运行 |
PROPAGATION_MANDATORY | 支持当前事务,假设当前没有事务,就抛出异常 |
PROPAGATION_REQUIRES_NEW | 新建事务,假设当前存在事务。把当前事务挂起 |
PROPAGATION_NOT_SUPPORTED | 以非事务方式运行操作。假设当前存在事务,就把当前事务挂起 |
PROPAGATION_NEVER | 以非事务方式运行,假设当前存在事务,则抛出异常 |
PROPAGATION_NESTED | 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。 |
Spring支持的隔离级别
事务隔离级别指的是一个事务对数据的修改与另一个并行的事务的隔离程度,当多个事务同时访问相同数据时,如果没有采取必要的隔离机制,就可能发生以下问题:
问题 | 描述 |
---|---|
脏读 | 一个事务读到另一个事务未提交的更新数据,所谓脏读,就是指事务A读到了事务B还没有提交的数据,比如银行取钱,事务A开启事务,此时切换到事务B,事务B开启事务–>取走100元,此时切换回事务A,事务A读取的肯定是数据库里面的原始数据,因为事务B取走了100块钱,并没有提交,数据库里面的账务余额肯定还是原始余额,这就是脏读 |
幻读 | 是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。 同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象 发生了幻觉一样。 |
不可重复读 | 在一个事务里面的操作中发现了未被操作的数据 比方说在同一个事务中先后执行两条一模一样的select语句,期间在此次事务中没有执行过任何DDL语句,但先后得到的结果不一致,这就是不可重复读 |
spring-mvc
- 客户端发送请求 DispatchServlet(中央控制器)接收请求
- 调用处理器映射找到处理器(HandleMapping)
- 返回HandleExecutionChain (handlerlntercepter【拦截器】Handler【处理器】)
- 通过处理器适配器调用具体的处理器(HandlerAdapter)–> 调用Handler(自定义的Controller)–>返回ModeAndView
- 在把ModeAndView返回给 DispatchServlet(中央控制器)
- DispatchServlet(中央控制器)–>通过ViewResolver(视图解析器)返回View对象
- DispatchServlet(中央控制器)把渲染后的视图返回给客户端
springBoot
自动装配
starter
名称 | 描述 |
---|---|
spring-boot-starter-thymeleaf | 使MVC Web applications 支持Thymeleaf |
spring-boot-starter-data-couchbase | 使用Couchbase 文件存储数据库、Spring Data Couchbase |
spring-boot-starter-artemis | 为JMS messaging使用Apache Artemis |
spring-boot-starter-web-services | 使用Spring Web Services |
spring-boot-starter-mail | Java Mail、Spring email为邮件发送工具 |
spring-boot-starter-data-redis | 通过Spring Data Redis 、Jedis client使用Redis键值存储数据库 |
spring-boot-starter-web | 构建Web,包含RESTful风格框架SpringMVC和默认的嵌入式容器Tomcat |
spring-boot-starter-activemq | 为JMS使用Apache ActiveMQ |
spring-boot-starter-data-elasticsearch | 使用Elasticsearch、analytics engine、Spring Data Elasticsearch |
spring-boot-starter-integration | 使用Spring Integration |
spring-boot-starter-test | 测试 Spring Boot applications包含JUnit、 Hamcrest、Mockito |
spring-boot-starter-jdbc | 通过 Tomcat JDBC 连接池使用JDBC |
spring-boot-starter-mobile | 通过Spring Mobile构建Web应用 |
spring-boot-starter-validation | 通过Hibernate Validator使用 Java Bean Validation |
spring-boot-starter-hateoas | 使用Spring MVC、Spring HATEOAS构建 hypermedia-based RESTful Web 应用 |
spring-boot-starter-jersey | 通过 JAX-RS、Jersey构建 RESTful web applications;spring-boot-starter-web的另一替代方案 |
spring-boot-starter-data-neo4j | 使用Neo4j图形数据库、Spring Data Neo4j |
spring-boot-starter-websocket | 使用Spring WebSocket构建 WebSocket 应用 |
spring-boot-starter-aop | 通过Spring AOP、AspectJ面向切面编程 |
spring-boot-starter-amqp | 使用Spring AMQP、Rabbit MQ |
spring-boot-starter-data-cassandra | 使用Cassandra分布式数据库、Spring Data Cassandra |
spring-boot-starter-social-facebook | 使用 Spring Social Facebook |
spring-boot-starter-jta-atomikos | 为 JTA 使用 Atomikos |
spring-boot-starter-security | 使用 Spring Security |
spring-boot-starter-mustache | 使MVC Web applications 支持Mustache |
spring-boot-starter-data-jpa | 通过 Hibernate 使用 Spring Data JPA (Spring-data-jpa依赖于Hibernate) |
spring-boot-starter | Core starter,包括 自动配置支持、 logging and YAML |
spring-boot-starter-groovy-templates | 使MVC Web applications 支持Groovy Templates |
spring-boot-starter-freemarker | 使MVC Web applications 支持 FreeMarker |
spring-boot-starter-batch | 使用Spring Batch |
spring-boot-starter-social-linkedin | 使用Spring Social LinkedIn |
spring-boot-starter-cache | 使用 Spring caching 支持 |
spring-boot-starter-data-solr | 通过 Spring Data Solr 使用 Apache Solr |
spring-boot-starter-data-mongodb | 使用 MongoDB 文件存储数据库、Spring Data MongoDB |
spring-boot-starter-jooq | 使用JOOQ链接SQL数据库;spring-boot-starter-data-jpa、spring-boot-starter-jdbc的另一替代方案 |
spring-boot-starter-jta-narayana | Spring Boot Narayana JTA Starter |
spring-boot-starter-cloud-connectors | 用连接简化的 Spring Cloud 连接器进行云服务就像Cloud Foundry、Heroku那样 |
spring-boot-starter-jta-bitronix | 为JTA transactions 使用 Bitronix |
spring-boot-starter-social-twitter | 使用 Spring Social Twitter |
spring-boot-starter-data-rest | 使用Spring Data REST 以 REST 方式暴露 Spring Data repositories |
spring-boot-starter-actuator | 使用Spring Boot Actuator 的 production-ready 功能来帮助你监视和管理应用 |
spring-boot-starter-undertow | 使用 Undertow 作为嵌入式服务容器;spring-boot-starter-tomcat的另一替代方案 |
spring-boot-starter-jetty | 使用 Jetty 作为嵌入式服务容器;spring-boot-starter-tomcat的另一替代方案 |
spring-boot-starter-logging | 为 logging 使用Logback.默认 logging starter |
spring-boot-starter-tomcat | 使用 Tomcat 作为嵌入式服务容器;作为默认嵌入式服务容器被spring-boot-starter-web使用 |
spring-boot-starter-log4j2 | 使用Log4j2记录日志;spring-boot-starter-logging的另一替代方案 |
自动装配的原理
1.在SpringBoot项目启动的时候,会加载SpringBootApplication这个注解
2.会解析@EnableAutoConfiguration注解
3.与之对应的解析@Import注解
4.执行ImportSelector接口的的实现
5.加载META-INF/spring-autoconfigure-metadata.properties中的注解元数据信息(过滤)
6.加载META-INF/spring.factories各种类路径【第三方扩展也同样的会加载对应的文件 SPI扩展机制】
springClode
什么是微服务
微服务架构就是将单一程序开发成一个微服务,每个微服务运行在自己的进程中,并使用轻量级的机制通信,通常是HTTP RESTFUL API。这些服务围绕业务能力来划分,并通过自动化部署机制来独立部署。这些服务可以使用不同的编程语言,不同数据库,以保证最低限度的集中式管理。
架构体系
单体架构
网站初期的架构越好,因为业务需要快速迭代和发布,单体架构开发和运维都很简单
集群架构
网站流量开始增加,服务器的性能出现瓶颈,通过集群架构进行横向扩容是最好的方式
垂直架构
垂直架构主要是用来解耦业务的复杂度,提高代码的维护性和可扩展性
SOA架构
SOA架构主要解决服务的复用性问题,它的核心目标是通过服务的抽象来实现业务功能的可复用性
微服务架构
微服务架构是在SOA架构思想之上的提炼,它是服务化思想的最佳时间方向和服务治理不断完善和交付链路逐步成熟后的自然产物
Spring Cloud提供的功能
服务注册与发现
服务路由
服务调用
统一配置管理
限流与熔断
Spring Cloud Netflix
网关: zuul
服务注册:eureka
负载均衡: ribbon
断路器: hystrix
Ribbon 负载均衡常见算法
随机/随机加权 RandomRule
轮询/加权 RoundRobinRule
hash算法
最小连接数
配置中心
- Apollo
- Diamond
- Disconf
- Nacos
- Spring cloud config