文章目录
- Spring aop ioc
- springboot配置文件 bootstrap与application 到底有什么区别?
- 什么是循环依赖,怎么解决?
- Spring 框架中都用到了哪些设计模式?
- Spring框架中的单例bean是线程安全的吗?
- aop常用注解
- spring常用注解
- @Autowired和@Resource之间的区别
- @RestController和@Controller有什么区别?
- @component和@Bean的区别
- @Controller怎么直接返回数据
- 如何给Spring 容器提供配置元数据?Spring有几种配置方式
- Spring事务的实现方式和实现原理
- Springboot事务不生效的几种情况
- Spring事务隔离级别有五种
- Springboot的优点
- Springcloud的优点
- springcloud与springcloud alibaba对应的组件
- 那如果现在微服务A远程调用B,B想获取请求头参数该怎么办?
- Nacos修改配置文件如何使其立即生效
Spring aop ioc
- AOP(面向切面)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。
实现AOP的主要设计模式就是动态代理。
Spring的动态代理有两种:一是JDK的动态代理;另一个是cglib动态代理。 - IOC(控制反转)就是依赖倒置原则的一种代码设计思路。就是把原先在代码里面需要实现的对象创建、对象之间的依赖,反转给容器来帮忙实现。
Spring IOC容器通过xml,注解等其它方式配置类及类之间的依赖关系,完成了对象的创建和依赖的管理注入。实现IOC的主要设计模式是工厂模式。
通过依赖注入DI实现ioc,DI底层使用的是反射机制来实现的。把java中对象的创建,赋值,依赖转交给spring容器管理。
IOC优点:集中管理,实现类的可配置和易管理。降低了类与类之间的耦合度。
springboot配置文件 bootstrap与application 到底有什么区别?
bootstrap 由父ApplicationContext加载,比application优先加载;
bootstrap里面的属性不能被覆盖
application 配置文件主要用于 Spring Boot 项目的自动化配置。
bootstrap 是应用程序的父上下文,也就是说 bootstrap 加载优先于 applicaton。
什么是循环依赖,怎么解决?
循环依赖(对象之间相互依赖),spring已经帮我们解决了。
使用setter注入不使用构造器注入的方式可以解决循环依赖的问题。
Spring 框架中都用到了哪些设计模式?
工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例;
单例模式:Bean默认为单例模式。
代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术;
模板方法:用来解决代码重复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate。
观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如Spring中listener的实现–ApplicationListener。
Spring框架中的单例bean是线程安全的吗?
不是,Spring框架中的单例bean不是线程安全的。
spring 中的 bean 默认是单例模式,spring 框架并没有对单例 bean 进行多线程的封装处理。
实际上大部分时候 spring bean 无状态的(比如 dao 类),所有某种程度上来说 bean 也是安全的,但如果 bean 有状态的话(比如 view model 对象),那就要开发者自己去保证线程安全了,最简单的就是改变 bean 的作用域,把“singleton”变更为“prototype”,这样请求 bean 相当于 new Bean()了,所以就可以保证线程安全了。
aop常用注解
@Aspect:声明当前类为切面类
@Around:指定环绕通知
@Pointcut:指定切入点表达式
@Before:在切入点方法执行前执行前置通知
@After:最终通知,终通知于切入点方法执行完成之后执行,无论切入点方法是否产生异常最终通知都会执行
@AfterReturning:在切入点方法正常执行后执行
@AfterThrowing:在切入点方法执行产生异常后执行
spring常用注解
@Controller:使用@Controller 注解的类会被Spring管理,使得该类能够通过 getBean() 或者 @Autowired 的方式从Spring容器中获取Bean实例。
@ResponseBody:@ResponseBody的作用其实是将java对象转为json格式的数据
@RestController:它结合了 @Controller 和 @ResponseBody 两个注解的功能
@Service:是业务逻辑层注解,这个注解只是标注该类处于业务逻辑层。
@Repository:注解在持久层中,具有将数据库操作抛出的原生异常翻译转化为spring的持久层异常的功能。
@Component: @Component注解的主要作用是标识一个类作为组件,使其可以被Spring框架管理。
@Configuration: @Configuration 的作用包括定义Bean、组织配置、替代XML配置、支持自动装配以及集成外部配置。
@Bean作用在方法上,用于生成bean的方法,并且交给Spring容器管理。
@SpringBootApplication:@SpringBootApplication 标注的类为 Spring Boot 的主配置类,Spring Boot会运行这个类的main方法来启动 Spring Boot 应用。
@ControllerAdvice作用是给Controller控制器添加统一的操作或处理,1.结合@ExceptionHandler用于全局异常的处理。2.搭配@ModelAttribute注解可以做全局数据绑定。3.全局数据预处理
@Autowired和@Resource之间的区别
- @Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为false)。如果需要按名称装配,可以结合@Qualifier注解使用。
@Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入。 - 依赖注入框架不同。@Autowired与Spring强耦合,如果使用非Spring框架,如JFinal,其功能将失效。而@Resource是Java标准,几乎所有支持JSR-250的框架都支持。
@RestController和@Controller有什么区别?
- @Controller 注解:使用@Controller 注解,在对应的方法上,视图解析器可以解析return 的jsp.html页面,并且跳转到相应页面若返回json等内容到页面,则需要加@ResponseBody注解
- @RestController注解:相当于@Controller+@ResponseBody两个注解的结合,返回json数据不需要在方法前面加@ResponseBody注解了
@component和@Bean的区别
如果想将第三方的类变成组件,你又没有没有源代码,也就没办法使用@Component进行自动配置,这种时候使用@Bean就比较合适了。不过同样的也可以通过xml方式来定义。
另外@Bean注解的方法返回值是对象,可以在方法中为对象设置属性。
Spring的Starter机制,就是通过@Bean注解来定义bean。
避免在某个项目中定义或者通过congfig注解来声明大量重复的bean。
@Bean则常和@Configuration注解搭配使用
@Configuration
public class WebSocketConfig {
@Bean
public Student student(){
return new Student();
}
}
@Controller怎么直接返回数据
- 在方法上加@ResponseBody
- 将@Controller换成@RestController
如何给Spring 容器提供配置元数据?Spring有几种配置方式
这里有三种重要的方法给Spring 容器提供配置元数据。
- XML配置文件。
- 基于注解的配置。
- 基于java的配置。
Spring事务的实现方式和实现原理
Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的。真正的数据库层的事务提交和回滚是通过binlog或者redo log实现的。
Springboot事务不生效的几种情况
- mysql存储引擎不支持事务。
MyISAM 引擎是不支持事务操作的,InnoDB 才是支持事务的引擎 - 没有被 Spring 管理
如果@Service 注解注释掉,这个类就不会被加载成一个 Bean,那这个类就不会被 Spring 管理了,事务自然就失效了 - 方法不是 public 的
@Transactional 只能用于 public 的方法上,否则事务不会失效,如果要用在非 public 方法上,可以开启 AspectJ 代理模式 - 异常被抓住了
try catch - 自身调用问题
来看两个示例:
@Service
public class OrderServiceImpl implements OrderService {
public void update(Order order) {
updateOrder(order);
}
@Transactional
public void updateOrder(Order order) {
// update order
}
}
update方法上面没有加 @Transactional 注解,调用有 @Transactional 注解的 updateOrder 方法,updateOrder 方法上的事务管用吗?
再来看下面这个例子:
@Service
public class OrderServiceImpl implements OrderService {
@Transactional
public void update(Order order) {
updateOrder(order);
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateOrder(Order order) {
// update order
}
}
这次在 update 方法上加了 @Transactional,updateOrder 加了 REQUIRES_NEW 新开启一个事务,那么新开的事务管用么?
这两个例子的答案是:不管用!
因为它们发生了自身调用,就调该类自己的方法,而没有经过 Spring 的代理类,默认只有在外部调用事务才会生效,这也是老生常谈的经典问题了。
这个的解决方案之一就是在的类中注入自己,用注入的对象再调用另外一个方法,这个不太优雅。
6. 异常类型错误
上面的例子再抛出一个异常:
@Service
public class OrderServiceImpl implements OrderService {
@Transactional
public void updateOrder(Order order) {
try {
// update order
} catch {
throw new Exception("更新错误");
}
}}
这样事务也是不生效的,因为默认回滚的是:RuntimeException(运行时异常),如果你想触发其他异常的回滚,需要在注解上配置一下,如:
@Transactional(rollbackFor = Exception.class)
这个配置仅限于 Throwable 异常类及其子类。
Spring事务隔离级别有五种
读未提交,读已提交 ,可重复,串行化,DEFAULT(使用数据库默认的事务隔离级别)
Springboot的优点
- 创建独立Spring应用
- 内嵌Tomcat服务器
- 自动starter依赖,简化构建配置
- 自动配置Spring以及第三方功能
- 提供生产级别的监控、健康检查以及外部优化配置
- 无代码生成、无需编写XML
Springcloud的优点
- 服务拆分粒度更细,有利于资源重复利用,有利于提高开发效率(按业务划分的微服务单元独立部署,运行在独立的进程中,服务与服务之间没有任何耦合,有很好的扩展性和复用性)
- 可以更精准的制定优化服务方案,提高系统的可维护性
- 微服务架构采用去中心化思想,服务之间采用Restful等轻量级通讯,比ESB更轻量
- 适于互联网时代,产品迭代周期更短
项目面临高并发,高性能,高可用
springcloud与springcloud alibaba对应的组件
springcloud | springcloud alibaba | |
---|---|---|
注册中心 | eureka | nacos |
配置中心 | springcloudconfig | nacos |
网关 | zuul | gateway |
熔断降级 | Hystrix | Sentinel |
服务调用 | openfeign | dubbo |
那如果现在微服务A远程调用B,B想获取请求头参数该怎么办?
每一次远程请求的时候都创建了一个新的Request Template对象,在该对象中不包含之前的请求头数据。默认情况下feign远程调用的时候不会传递请求头!
方案一:在feign接口上添加对应的形式参数即可
弊端:每一个接口想要获取参数都需要在接口方法上添加对应的形式参数.影响代码效率
方案二:使用OpenFeign中的拦截器(RequestInterceptor)来拦截请求,添加请求头。
Nacos修改配置文件如何使其立即生效
实现nacos配置更新不重启微服务生效,但需要两种配置实现。
- 在引用(如@Value)nacos配置的类上添加@RefreshScope。(此注解能刷新配置文件,但只对添加了此注解的类有效,并非全局有效)
application.yml
test:
value: nacos
public class TestConfig {
@Value("${test.value}")
private String applicationValue;
}
- 使用@ConfigurationProperties注解,在其注解后添加配置文件的前缀,前缀和属性名拼接等于nacos配置中的名字即可生效。
application.yml
test:
value: nacos
@ConfigurationProperties(prefix = "test")
public class TestConfig {
private String value;
}
注意事项:
不是所有的配置都适合放到配置中心,否则维护起来比较繁锁;
建议将一些关键参数、需要运行时调整的参数放到nacos配置中心,一般是自定义配置;