SpringBoot2

SpringBoot2

微服务的概念

微服务就是将一个大的系统拆分成多个子系统,然后通过REST风格的请求将他们集成起来,进一步简化了分布式系统的开发

SpringBoot2的特点

  • 约定大于配置,通过引入xx-starter加上自定义的配置文件就可以集成某个组件的java客户端
  • 内置tomcat/undertow
  • 提供快速的测试环境

为什么要学这个

每天都在用SpringBoot缺不知道其中的原理,典型的日用而不知。一旦出现开发的问题,就是一顿博客乱找,很久也解决不了问题 所以,理解原理很重要

Bean的声明周期

1.Spring通过配置,如@SpringBootApplication或@ComponentScan定义的路径(默认为当前包和子包)找到带有@Component的类

2.解析类定义,把Bean定义发布到Ioc容器中,注意:是定义,不是实例

3.Ioc容器装载Bean的定义

4.创建Bean的实例对象

5.开始扫描@Autowired注入各类资源

踩坑

@Service
public class Service{
    @Autowired
    public String kafkaHost;
    
    public KafkaAppender;
    public Service(){
        KafkaAppender = new KafkaAppender(kafkaHost);
    }
}
复制代码

注意,当Service被初始化时,会调用构造器,此时kafkaHost还没被Autowired注入,所以这个时候kafkaHost为null

Spring注解说明

Spring注解之Bean注解:
@Configuration
public class AppConfig {
    @Bean(name="user"} 
    public User initUser () {
        User user= new User (); 
        user.setId(100) ;
        user.setUserName();
        return user;
    }
}

@Service    
public class System{
    @Autowired
    private User user;
}   
复制代码

@Bean表示将initUser返回的user装配到Ioc中,而且该bean的name为user。如果没有定义name,则bean的name为方法名(initUser)

@ComponentScan与@Component
@Component("user")
public class User {
    private id; 
    private String userName; 
    private String note;
}

@Service    
public class System{
    @Autowired
    private User user;
}    
复制代码
注意事项
  • @Component注解作用域默认为singleton
  • @Component表名这个类将被Ioc装配,而且该bean的name为user,如果没有显示定义name,则以类名第一个字母小写作为bean的name
  • @Component使用在不确定哪一个层的时候使用,可以作用在任何层次,把普通pojo实例化到spring容器
  • 不推荐使用@Component注解,而应该使用它的扩展,如@Service、@Repository

业务组件的注释

  • @Component 没有明确角色的组件
  • @Service 在业务逻辑层(Service层)使用
  • @Repository 在数据访问层(dao层)使用
  • @Controller 用于标注控制层组件
  • @RestController 纯REST风格的控制器
@Service
@Service注解作用在类上
@Service注解作用域默认为singleton
使用注解配置和类路径扫描时,被@Service注解标注的类会被Spring扫描并注册为Bean
@Service注解用于标注业务的逻辑组件,即服务组件组件
复制代码
@Repository
@Repository注解作用在类上
@Repository注解作用域默认为singleton
使用注解配置和类路径扫描时,被@Repository注解标注的类会被Spring扫描并注册为Bean
@Repository注解用于标注数据访问组件,即DAO组件
@Repository注解的作用不只是将类识别为Bean,同时它还能将所标注的类中抛出的数据访问异常封装为 Spring 的数据访问异常类型
复制代码
@Controller
@Controller注解作用在类上
使用注解配置和类路径扫描时,被@Controller注解标注的类会被Spring扫描并注册为Bean
@Controller用于标注Web中控制层组件
被@Controller标注的类负责处理由DispatcherServlet分发的请求,
它把用户请求的数据经过业务处理层处理之后封装成一个Model ,然后再把该Model返回给对应的View进行展示
@Controller和@RequestMapping、@RequestParam等一些注解共同处理URL的映射
复制代码

@ComponentScan意味着扫描当前注释类所在的包和子包

@SpringBootApplication

@SpringBootApplication默认包含了@ComponentScan

@Autowired、@Primary、@Qualifier

Spring最常用的注解,根据类型找到对应的Bean进行注入,也就是getBeanByType()

  • 首先根据类型找到对应类型的Bean,如果不唯一,则按照Bean名称进行匹配,如果还找不到,就抛异常
  • 当对应类型的Bean有多个时,@Primary告诉Ioc容器,优先使用带有@Primary标识的Bean
public interface User {
}
@Component
@Primary
public class Man implements {
}
@Component
public class Woman implements {
}

public class System{
    @Autowired
    private User user;
    这里装配的是Woman
}
复制代码
  • @Qualifier告诉Ioc容器按照类型和名称去找到对应的Bean
public interface User {
}
@Component
@Primary
public class Man implements {
}
@Component
@Primary
public class Woman implements {
}

public class System{
    @Autowired
    @Qualiefier("man")
    private User user;
    这里装配的是Man
    
    public void heiheihei(@Autowired @Qualiefier("man") User user){};
}
复制代码
@Value与@ConfigurationProperties

从配置文件中获取属性

@Component
@ConfigurationProperties(prefix = "microservice.quickstart")
public class User{
    @Value('${user.name}')
    private String userName;
    //读取配置文件中的microservice.quickstart.user.name配置
}

复制代码
多环境配置下的启动

按照工程建立

  • application.properties
  • application-dev.properties
  • application-test.properties
  • application-prd.properties 启动时添加命令作为参数 java -jar xx.jar -Dpsirng.profiles.active=dev java -jar xx.jar -Dpsirng.profiles.active=test java -jar xx.jar -Dpsirng.profiles.active=prd
@Scope作用在类上和方法上

@Scope用来配置Bean的作用域,有以下几种

singleton单例模式

Spring 容器中有且只有一个Bean实例,只要Spring容器不销毁或退出,该Bean实例就会一直存活

prototype原型模式

每次获取Bean的时候会有一个新的实例,Spring容器不能对返回Bean实例的整个生命周期负责

request模式

request只适用于Web程序,每一次HTTP请求都会产生一个新的bean, 同时该bean仅在当前HTTP request内有效,当请求结束后,该对象的生命周期即告结束

session模式

session只适用于Web程序,session作用域表示该针对每一次HTTP请求都会产生一个新的bean, 同时该bean仅在当前HTTP session内有效

application模式

application只适用于Web程序,全局作用域

@Conditional(TestCondition.class)

这句代码可以标注在类上面,表示该类下面的所有@Bean都会启用配置,也可以标注在方法上面,只是对该方法启用配置。

@ConditionalOnBean(仅仅在当前上下文中存在某个对象时,才会实例化一个Bean) @ConditionalOnClass(某个class位于类路径上,才会实例化一个Bean) @ConditionalOnExpression(当表达式为true的时候,才会实例化一个Bean) @ConditionalOnMissingBean(仅仅在当前上下文中不存在某个对象时,才会实例化一个Bean) @ConditionalOnMissingClass(某个class类路径上不存在的时候,才会实例化一个Bean) @ConditionalOnNotWebApplication(不是web应用)

spring源码阅读

@EnableWebMvc、WebMvcConfigurationSupport和WebMvcConfigurationAdapter三者之间的区别是什么 @EnableWebMvc注解的类等于extends WebMvcConfigurationSupport 但是没有重写任何方法 SpringBoot WebMVC的自动配置信息都在WebMvcAutoConfiguration这个类中,我们看他的源码

@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
@AutoConfigureOrder(-2147483638) //Bean的初始化顺序
@AutoConfigureAfter({DispatcherServletAutoConfiguration.class, ValidationAutoConfiguration.class})
public class WebMvcAutoConfiguration {
复制代码

其中@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})的意思是,当工程中没有WebMvcConfigurationSupport 时,才会使用WebMvc的自动配置;我们一般会继承WebMvcConfigurationSupport来自定义配置类, 但是一旦继承WebMvcConfigurationSupport后就会出现新的问题: 会发现Spring Boot的WebMvc自动配置失效,具体表现比如访问不到静态资源(js,css等)了。

拦截器原理

动态代理

上海体育公园有很多大爷大妈相亲,你要去寻找女朋友。这时,你就问大妈:女儿喜欢什么呀,大妈可能会替她回答。 当然,大妈觉得你发际线太高,他也可以直接拒绝。这时,这个大妈就是她女儿的代理

JDK中的使用方式

JDK提供了类Proxy的静态方法:newProxyInstance.

public static Object newProxyInstance(ClassLoader var0, Class<?>[] var1, InvocationHandler var2) throws IllegalArgumentException

这里的invocationHandler是一个接口InvocationHandler对象,定义了invoke方法,这个方法就是实现代理对象逻辑的 通过target\method\args就能够用反射方法运行了

具体见:ProxyBean.java[请学会用IDEA找到对应名字的类]

AOP约定流程

按照我们上面实现的代码,可以看到,AOP是一种规范化的约定,我们按照这种约定来使用,就可以实现动态代理 aop-principle.png

拦截器使用AOP的约定

spring-intercetor.png

Spring中使用@AspectJ

Spring AOP使用@AspectJ对方法进行拦截,所以,我们要先确定什么地方需要AOP,也就是连接点 有了连接点后,我们需要一个切面,用来描述流程的织入 请看案例:

MyAspect.java

Myabits中的数据库事务

@Transactional可以放在方法上,也可以放在类上 如果放在类上,则该类的所有方法都默认带了@Transactional 案例请查看

com.liuyiling.microservice.api.controller.DataBaseController.transactional

注意事项
  • @Transactional必须加在public方法上,否则CGlib代理会找不到
  • 正确的设置@Transactional 的 isolation 属性

事务的隔离度,默认值采用 DEFAULT

  • 事务必须注解在非自调用方法上,下面面这个例子事务将不会被调用
@Service
public class OrderService {
    private void insert() {
        insertOrder();
    }
    
    @Transactional
    public void insertOrder() {
    }
}
复制代码
  • 可以指定事务的回滚条件

默认情况下,如果在事务中抛出了未检查异常(继承自 RuntimeException 的异常)或者 Error,则 Spring 将回滚事务;除此之外,Spring 不会回滚事务。 如果在事务中抛出其他类型的异常,并期望 Spring 能够回滚事务,可以指定 rollbackFor。例: @Transactional(propagation= Propagation.REQUIRED,rollbackFor= MyException.class)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值