欧博官网代理

乐鱼炸金花打不开解决方法_Spring 处理轮回依赖只使用二级缓存,不错吗?

发布日期:2023-10-30 04:53    点击次数:174

乐鱼炸金花打不开解决方法_Spring 处理轮回依赖只使用二级缓存,不错吗?

乐鱼炸金花打不开解决方法_ 什么是轮回依赖?

先说一下什么是轮回依赖,Spring在运更始A的手艺需要注入B,而运更始B的手艺需要注入A,在Spring启动后这2个Bean齐要被运更始完成。

Spring的轮回依赖有4种场景:

构造器的轮回依赖(singleton,prototype) 属性的轮回依赖(singleton,prototype)

「spring咫尺只救济singleton类型的属性轮回依赖」

构造器的轮回依赖
@Component 亚新百家乐public class ConstructorA {   private ConstructorB constructorB;   @Autowired  public ConstructorA(ConstructorB constructorB) {   this.constructorB = constructorB;  } } 
@Component public class ConstructorB {   private ConstructorA constructorA;   @Autowired  public ConstructorB(ConstructorA constructorA) {   this.constructorA = constructorA;  } } 
@Configuration @ComponentScan("com.javashitang.dependency.constructor") public class ConstructorConfig { } 
public class ConstructorMain {   public static void main(String[] args) {   AnnotationConfigApplicationContext context =     new AnnotationConfigApplicationContext(ConstructorConfig.class);   System.out.println(context.getBean(ConstructorA.class));   System.out.println(context.getBean(ConstructorB.class));  } } 

运行ConstructorMain的main法度的手艺会在第一转就报格外,施展Spring没目标运更始通盘的Bean,即上头这种风景的轮回依赖Spring无法措置。

「构造器的轮回依赖,不错在构造函数中使用@Lazy注解蔓延加载。在注入依赖时,先注入代理对象,当初次使用时再创建对象完成注入」

皇冠信用盘hga006
@Autowired public ConstructorB(@Lazy ConstructorA constructorA) {  this.constructorA = constructorA; } 

因为咱们主要温雅属性的轮回依赖,构造器的轮回依赖就不作念过多分析了。

新2足球网址大全 属性的轮回依赖

先演示一下什么是属性的轮回依赖。

@Data @Component public class A {      @Autowired     private B b; } 
@Data @Component public class B {      @Autowired     private A a; } 
@Configuration @EnableAspectJAutoProxy @ComponentScan("com.javashitang.dependency") public class Config { } 
public class Main {      public static void main(String[] args) {         AnnotationConfigApplicationContext context =                 new AnnotationConfigApplicationContext(Config.class);         System.out.println(context.getBean(A.class).getB() == context.getBean(B.class));         System.out.println(context.getBean(B.class).getA() == context.getBean(A.class));     } } 

Spring容器平素启动,运行成果为true,念念兑现肖似的功能并不难,我写个demo演示一下。

打不开解决方法
public class DependencyDemoV1 {      private static final Map<String, Object> singletonObjects =             new HashMap<>(256);      @SneakyThrows     public static <T> T getBean(Class<T> beanClass) {         String beanName = beanClass.getSimpleName();         if (singletonObjects.containsKey(beanName)) {             return (T) singletonObjects.get(beanName);         }         // 实例化bean         Object object = beanClass.getDeclaredConstructor().newInstance();         singletonObjects.put(beanName, object);         // 脱手运更始bean,即填充属性         Field[] fields = object.getClass().getDeclaredFields();         for (Field field : fields) {             field.setAccessible(true);             // 获得需要注入字段的class             Class<?> fieldClass = field.getType();             field.set(object, getBean(fieldClass));         }         return (T) object;     }      public static void main(String[] args) {         // 假装扫描出来的类         Class[] classes = {A.class, B.class};         for (Class aClass : classes) {             getBean(aClass);         }         System.out.println(getBean(A.class).getB() == getBean(B.class));         System.out.println(getBean(B.class).getA() == getBean(A.class));     }  } 

「在脱手背面的实质的手艺,咱们先明确2个主见」

实例化:调用构造函数将对象创建出来 运更始:调用构造函数将对象创建出来后,给对象的属性也被赋值。

不错看到只用了一个map就兑现了轮回依赖的兑现,但这种兑现存个小弱势,singletonObjects中的类有可能仅仅完成了实例化,并莫得完成运更始。

网站致力于广大博彩爱好者提供安全、稳定博彩平台多样化博彩游戏赛事直播,博彩攻略技巧分享,您博彩游戏中尽情享受乐趣收益。平台操作简便,充值提款方便快捷,您提供最佳博彩体验最高博彩收益。

而在spring中singletonObjects中的类齐完成了运更始,因为咱们取单例Bean的手艺齐是从singletonObjects中取的,不成能让咱们获得到莫得运更始完成的对象。

是以咱们来写第二个兑现,「用singletonObjects存运更始完成的对象,而用earlySingletonObjects暂存实例化完成的对象,等对象运更始结束再将对象放入singletonObjects,并从earlySingletonObjects删除」。

public class DependencyDemoV2 {      private static final Map<String, Object> singletonObjects =             new HashMap<>(256);      private static final Map<String, Object> earlySingletonObjects =             new HashMap<>(256);      @SneakyThrows     public static <T> T getBean(Class<T> beanClass) {         String beanName = beanClass.getSimpleName();         if (singletonObjects.containsKey(beanName)) {             return (T) singletonObjects.get(beanName);         }         if (earlySingletonObjects.containsKey(beanName)) {             return (T) earlySingletonObjects.get(beanName);         }         // 实例化bean         Object object = beanClass.getDeclaredConstructor().newInstance();         earlySingletonObjects.put(beanName, object);         // 脱手运更始bean,即填充属性         Field[] fields = object.getClass().getDeclaredFields();         for (Field field : fields) {             field.setAccessible(true);             // 获得需要注入字段的class             Class<?> fieldClass = field.getType();             field.set(object, getBean(fieldClass));         }         singletonObjects.put(beanName, object);         earlySingletonObjects.remove(beanName);         return (T) object;     }      public static void main(String[] args) {         // 假装扫描出来的类         Class[] classes = {A.class, B.class};         for (Class aClass : classes) {             getBean(aClass);         }         System.out.println(getBean(A.class).getB() == getBean(B.class));         System.out.println(getBean(B.class).getA() == getBean(A.class));     }  } 

咫尺的兑现和spring保合手一致了,况且只用了2级缓存。spring为什么搞第三个缓存呢?「第三个缓存主要和代理对象关联」

皇冠分红

我如故把上头的例子改良一下,改成用3级缓存的兑现:

public interface ObjectFactory<T> {     T getObject(); } 
public class DependencyDemoV3 {      private static final Map<String, Object> singletonObjects =             new HashMap<>(256);      private static final Map<String, Object> earlySingletonObjects =             new HashMap<>(256);      private static final Map<String, ObjectFactory<?>> singletonFactories =             new HashMap<>(256);      @SneakyThrows     public static <T> T getBean(Class<T> beanClass) {         String beanName = beanClass.getSimpleName();         if (singletonObjects.containsKey(beanName)) {             return (T) singletonObjects.get(beanName);         }         if (earlySingletonObjects.containsKey(beanName)) {             return (T) earlySingletonObjects.get(beanName);         }         ObjectFactory<?> singletonFactory = singletonFactories.get(beanName);         if (singletonFactory != null) {             return (T) singletonFactory.getObject();         }         // 实例化bean         Object object = beanClass.getDeclaredConstructor().newInstance();         singletonFactories.put(beanName, () -> {             Object proxy = createProxy(object);             singletonFactories.remove(beanName);             earlySingletonObjects.put(beanName, proxy);             return proxy;         });         // 脱手运更始bean,即填充属性         Field[] fields = object.getClass().getDeclaredFields();         for (Field field : fields) {             field.setAccessible(true);             // 获得需要注入字段的class             Class<?> fieldClass = field.getType();             field.set(object, getBean(fieldClass));         }         createProxy(object);         singletonObjects.put(beanName, object);         singletonFactories.remove(beanName);         earlySingletonObjects.remove(beanName);         return (T) object;     }      public static Object createProxy(Object object) {         // 因为这个法度有可能被实施2次,欧博游戏平台是以这里应该有个判断         // 如果之前提前进行过aop操作则平直复返,知谈意旨有趣有趣就行,不写了哈         // 需要aop的话则复返代理对象,不然复返传入的对象         return object;     }      public static void main(String[] args) {         // 假装扫描出来的类         Class[] classes = {A.class, B.class};         for (Class aClass : classes) {             getBean(aClass);         }         System.out.println(getBean(A.class).getB() == getBean(B.class));         System.out.println(getBean(B.class).getA() == getBean(A.class));     }  } 

「为什么要包装一个ObjectFactory对象?」

如果创建的Bean有对应的aop代理,那其他对象注入时,注入的应该是对应的代理对象;「然则Spring无法提前知谈这个对象是不是有轮回依赖的情况」,而平素情况下(莫得轮回依赖情况),Spring齐是在对象运更始后才创建对应的代理。这手艺Spring有两个遴荐:

从文字记载可以查到的龚自珍故居有三处:杭州一处,即杭州城东马坡巷6号,那是他的出生地,现为龚自珍纪念馆;北京两处,分别为西城区手帕胡同21号和上斜街50号。

全球儿童肥胖患病率显著上升,2020年全球估计有3890万(5.7%)5岁以下儿童超重肥胖。儿童超重肥胖是一个重要的临床和公共卫生问题,会改变儿童代谢状态,导致血脂异常、胰岛素抵抗和炎症等。虽然与正常体重儿童相比,超重肥胖儿童更有可能发生代谢紊乱和心血管异常,但同样BMI水平的儿童代谢情况存在显著异质性,即不同的肥胖代谢表型。与代谢异常的超重肥胖儿童不同,部分超重肥胖儿童并未出现代谢紊乱的情况;同时,部分正常体重儿童也会发生代谢异常。

岂论有莫得轮回依赖,实例化后就平直创建好代理对象,并将代理对象放入缓存,出现轮回依赖时,其他对象平直就不错取到代理对象并注入(只需要2级缓存,singletonObjects和earlySingletonObjects即可) 「不提前创建好代理对象,在出现轮回依赖被其他对象注入时,才提前生成代理对象(此时只完成了实例化)。这么在莫得轮回依赖的情况下,Bean如故在运更始完成才生成代理对象」(需要3级缓存) 「是以到咫尺边界你知谈3级缓存的作用了把,主如果为了平素情况下,代理对象能在运更始完成青年景,而毋庸提前生成」 缓存 施展 singletonObjects 第一级缓存,存放运更始完成的Bean earlySingletonObjects 第二级缓存,存放实例化完成的Bean,有可能被进行了代理 singletonFactories 蔓延生成代理对象 源码解析

获得Bean的手艺先尝试从3级缓存中获得,和咱们上头的Demo差未几哈!

DefaultSingletonBeanRegistry#getSingleton

当从缓存中获得不到时,会进行创建 AbstractAutowireCapableBeanFactory#doCreateBean(删除了部分代码哈)

发生轮回依赖时,会从工场里获得代理对象哈!

当开启aop代理时,SmartInstantiationAwareBeanPostProcessor的一个兑现类有AbstractAutoProxyCreator

乐鱼炸金花皇冠信用盘要押金吗

AbstractAutoProxyCreator#getEarlyBeanReference

getEarlyBeanReference法度提前进行代理,为了退避背面再次进行代理,需要用earlyProxyReferences记载一下,这个Bean如故被代理过了,毋庸再代理了。

AbstractAutoProxyCreator#postProcessAfterInitialization

火狐体育官方入口

这个法度是进行aop代理的场所,因为有可能提前代理了,是以先把柄earlyProxyReferences判断一下,是否提前代理了,提前代理过就毋庸代理了。

当bean运更始结束,会放入一级缓存,并从二三级缓存删除。

DefaultSingletonBeanRegistry#addSingleton

竞争

皇冠客服飞机:@seo3687

皇冠体育hg86a

发生轮回依赖时,举座的实施经由如下:

本文转载自微信公众号「Java识堂」,不错通过以下二维码温雅。转载本文请相干Java识堂公众号。