当前位置: 首页 > news >正文

自己做下载类网站重庆百度seo公司

自己做下载类网站,重庆百度seo公司,做赌博网站是什么案件,云南网站备案查询文章目录 1、单例Bean不是线程安全的2、AOP3、Spring中事务的实现4、Spring事务失效的场景4.1 情况一:异常被捕获4.2 情况二:抛出检查异常4.3 注解加在非public方法上 5、Bean的生命周期6、Bean的循环引用7、Bean循环引用的解决:Spring三级缓…

文章目录

  • 1、单例Bean不是线程安全的
  • 2、AOP
  • 3、Spring中事务的实现
  • 4、Spring事务失效的场景
    • 4.1 情况一:异常被捕获
    • 4.2 情况二:抛出检查异常
    • 4.3 注解加在非public方法上
  • 5、Bean的生命周期
  • 6、Bean的循环引用
  • 7、Bean循环引用的解决:Spring三级缓存
  • 8、构造方法出现循环依赖
  • 9、面试

1、单例Bean不是线程安全的

@Scope注解下,singleton表示Bean在IOC容器中只有一个实例,prototype则表示一个Bean可以有多个实例

在这里插入图片描述

但单例Bean不是线程安全的,Demo代码如下:线程1进来count被改成1,线程2进来,count被改成10,线程交替执行,就乱套了,单例Bean UserController就不线程安全

在这里插入图片描述
多个用户同时请求一个微服务,每个请求对应一个线程,如果并发的这段代码中,对单例的成员属性修改了,则存在线程安全问题。上面例子中,UserController这个Bean的成员属性count在被并发修改(存在可修改的成员变量),此时,单例的Bean不是线程安全的。相反,UserService的这个Bean,是不可变状态(不涉及其成员属性的修改),因此,UserService的这个单例Bean是线程安全的。

最后,补充一句,/getById/{id},id属于局部变量,更无线程安全问题了。

2、AOP

项目相关:做链路追踪埋点,采集所有接口的数据库层、Redis执行时间等信息,采用了AOP实现。

AOP,面向切面编程,将那些公共的逻辑代码,抽取封装,匹配要切入的点,实现统一加功能的操作。减少了系统的重复代码,提高了可维护性。其使用场景如自己做公共日志采集上报、Spring用来实现事务

在这里插入图片描述

3、Spring中事务的实现

Spring中,事务的实现可以编程式,也可以声明式。前者使用TransactionTemplate实现,对业务代码有侵入性。后者使用@Transactional注解。加注解实现事务,底层用的是AOP:

在这里插入图片描述
实现如上:切点表达式匹配@Transactional注解,使用环绕通知,执行前,加开启事务的代码,执行后,加提交事务的代码,出现异常,回滚事务。

4、Spring事务失效的场景

4.1 情况一:异常被捕获

如下:不加try-catch,发生异常后,事务回滚。加了try-catch,发生异常后,被catch捕获处理了。@Transactional对应的AOP没有收到异常,就会去提交事务。导致了异常后面的业务代码没执行,就会出现转账账户扣钱了,但被转账的用户余额不变的情况。

在这里插入图片描述

4.2 情况二:抛出检查异常

以下,读取的文件不存在,抛出了FileNotFound异常,但事务并不会回滚

在这里插入图片描述

因为Spring默认只会回滚非检查异常(RunTimeException),解决办法是,添加属性,指明事务回滚的异常种类,以下写法即只要发生异常就回滚:

@Transactional(rollbackFor=Exception.class)

4.3 注解加在非public方法上

在这里插入图片描述
Spring为方法创建代理,AOP添加事务通知的前提是:方法是public的,此时需要改为public方法

5、Bean的生命周期

首先,Spring容器将xml中的<bean>信息封装成一个个BeanDefinition对象(该接口的相关方法如下,可获取全类名、初始化方法、作用域,其中后面步骤的初始化,也是从这儿BeanDefition拿的方法名)

在这里插入图片描述
接下来:⇒

STEP1:实例化

  • 由BeanDefinition拿到构造方法,通过反射去拿到构造函数来(new Instance)实例化,拿到空对象,即纯净态的Bean
  • 当然实例化也可能是实例工厂、静态工厂等

STEP2:属性赋值

  • 解析自动装配(DI的体现),可byName、byType、constractor
  • 这里当然还有循环依赖的情况

STEP3:初始化

  • 调用那些XXXAware的回调方法
  • 调用初始化生命周期的回调方法(init-method)
  • 如果Bean涉及了AOP,还要为这个Bean创建动态代理

STEP4:销毁

  • 在Spring容器关闭的时候调用
  • 调用销毁生命周期的回调方法(destroy-method)

在这里插入图片描述

注意Bean前置处理器和Bean后置处理器的执行时机,是在Bean的init方法执行前后。一般来说,框架中,Bean创建动态代理,常用后置处理器,即实现BeanPostProcessor。代码验证下:

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;@Component
public class User implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean {public User() {System.out.println("User的构造方法执行了.........");}private String name ;@Value("张三")		//依赖注入public void setName(String name) {System.out.println("setName方法执行了.........");}@Overridepublic void setBeanName(String name) {System.out.println("setBeanName方法执行了.........");}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {System.out.println("setBeanFactory方法执行了.........");}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {System.out.println("setApplicationContext方法执行了........");}@PostConstructpublic void init() {System.out.println("init方法执行了.................");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("afterPropertiesSet方法执行了........");}@PreDestroypublic void destory() {System.out.println("destory方法执行了...............");}}

关于前置处理器和后置处理器接口的实现:指定如果是user的Bean,就打印一句话。前面提到,框架中,Bean创建动态代理,常用后置处理器。下面就体现了模拟框架动态代理,给user这个Bean做cglib动态代理的效果:

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.InvocationHandler;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;@Component
public class MyBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (beanName.equals("user")) {System.out.println("postProcessBeforeInitialization方法执行了->user对象初始化方法前开始增强....");}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (beanName.equals("user")) {System.out.println("postProcessAfterInitialization->user对象初始化方法后开始增强....");//cglib代理对象Enhancer enhancer = new Enhancer();//设置需要增强的类enhancer.setSuperclass(bean.getClass());//执行回调方法,增强方法enhancer.setCallback(new InvocationHandler() {@Overridepublic Object invoke(Object o, Method method, Object[] objects) throws Throwable {//执行目标方法return method.invoke(method,objects);}});//创建代理对象return enhancer.create();}return bean;}}

效果:

在这里插入图片描述

6、Bean的循环引用

如下,A这个Bean创建时,依赖B这个Bean。而B这个Bean的创建,又依赖A这个Bean,即循环引用。有点死锁的感觉。

在这里插入图片描述
由Bean的生命周期可知,刚开始,从Beanfinition获取构造方法,反射拿到半成品的A这个Bean,即纯净态的Bean,此时,没有依赖注入,即b属性为null。

接下来,对A这个Bean进行初始化,需要依赖注入,设置b的属性,此时就需要从IoC容器中拿到B这个Bean。很明显,容器中没有,因此,去创建B这个Bean。

同A,纯净态的B,在实例化时,依赖注入,设置a的属性,发现需要A这个Bean。于是又走到了实例化A这条线路。到此,闭环了,走不出来了。

在这里插入图片描述

7、Bean循环引用的解决:Spring三级缓存

Spring框架已经帮开发者解决了大部分的循环引用 ⇒ 三级缓存(三个Map )

在这里插入图片描述

三个Map中存的分别是:单例已经走完全部流程的成熟态Bean、存半成品的Bean、对象工厂

在这里插入图片描述

一级缓存作用是:限制 bean 在 beanFactory 中只存一份,即实现 singleton scope。 仅靠它解决不了循环引用,还是会从1-6步一直循环:

在这里插入图片描述

引入二级缓存后,将原始对象A放入二级缓存,再去找B这个Bean。同理,B的原始对象也会先放入二级缓存。接下来B需要依赖注入A这个Bean时,会去从二级缓存中获取,然后B这个Bean创建成功,存储到一级缓存的单例池中,同时,将B在二级缓存中的半成品删掉。再回到造A的路上,将B从容器中注入到A,A也创建成功,将A在二级缓存中的半成品也删掉。

在这里插入图片描述

到此,一般对象之间的循环引用到二级缓存就解决了。但还有个场景,如果主要注入的A对象是个代理对象,则需要三级缓存:

在这里插入图片描述

8、构造方法出现循环依赖

Spring三级缓存解决了大部分的循环依赖(set注入时的循环依赖),但如果是构造方法的循环依赖,则需自己处理。如下写法,报错:Is there an unresolvable circular reference?

在这里插入图片描述
Bean的生命周期第一步,是通过BeanDefinition获取方法名,反射去拿到构造函数来(new Instance)实例化一个纯净态的Bean,还没到set依赖注入这一步(依赖注入的方式不是set方法,而是构造函数),就发现需要一个B这个Bean,同理B一开始执行构造方法就需要A这个Bean。此时Spring框架的三级缓存不能解决。需要加 @Lazy

在这里插入图片描述

9、面试

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

http://www.mmbaike.com/news/99764.html

相关文章:

  • 北京网站改版多少钱营销策划
  • 做网站是什么工作网络营销推广方案3篇
  • 网站建设工作室需要哪些设备整合营销传播案例分析
  • 网站文章收录慢广东seo教程
  • 东莞做税务登记的是哪个网站免费网站申请域名
  • wordpress垃圾箱在哪里网站优化比较好的公司
  • 江苏省建设工程网站系统怎么创建私人网站
  • 2018网站内容和备案长沙关键词快速排名
  • 动态网站设计的目的谷歌浏览器官网
  • 网站群建设成本分析最新国际新闻50条简短
  • 专门做母婴的网站电商运营方案
  • 聊城开发区建设局网站静态网站开发
  • 做微博网站好不好seo是干啥的
  • 南平建设局网站首页关键词怎么排名靠前
  • 哪个网站音乐做的最好自己做网站制作流程
  • 做独立网站需要注意些什么意思万能bt搜索引擎网站
  • 做网站专题需要什么软件北京seo关键词优化收费
  • 网站百度不收录站长资源平台
  • 济南网络营销服务公司百度关键词seo排名
  • 建设网站项目概述怎么才能在百度上打广告
  • 做网站公司郑州郑州的网站建设公司哪家好大冶seo网站优化排名推荐
  • 建设银行住房公积金预约网站培训平台
  • 阿里云建站视频网络信息发布平台
  • 网站与网页什么软件可以推广
  • 哪些网站做任务赚钱宣传软文案例
  • 营销型企业网站项目策划表青岛seo网站管理
  • 推广普通话奋进新征程手抄报徐州seo推广优化
  • 安徽省六安市城乡建设厅网站广州关键词seo
  • 用ps做网站导航游戏交易平台
  • 做网站直接开二级域名百度快速收录提交工具