备战2022春招-java-day14

Spring

  • spring4 => springboot1
  • spring5 => springboot2

SpringAOP顺序

Spring4
  • 正常执行:@Before(前置通知) ===> @After(后置通知) ===> @AfterReturning(正常返回)
  • 异常执行:@Before(前置通知) ===> @After(后置通知) ===> @AfterThrowing(方法异常)
Spring5
  • 正常执行;@Before(前置通知) ===> @AfterReturning(正常返回) ===> @After(后置通知)
  • 异常执行:@Before(前置通知) ===> @AfterThrowing(方法异常) ===> @After(后置通知)

Spring循环依赖

  1. 什么是循环依赖?
    多个bean之间相互依赖,形成了一个闭环。比如:A依赖于B、B依赖于C、C依赖于A。
    在这里插入图片描述
  2. 循环依赖两种情况?
    • 构造器注入: 会抛出BeanCurrentlyInCreationException。即则可能会创建无法解决的循环依赖场景。
    @Component
    public class ServiceA {
    
        private ServiceB serviceB;
    
        public ServiceA(ServiceB serviceB) {
            this.serviceB = serviceB;
        }
    }
    @Component
    public class ServiceB {
    
        private ServiceA serviceA;
    
        public ServiceB(ServiceA serviceA) {
            this.serviceA = serviceA;
        }
    }
    public class ClientConstruct {
        public static void main(String[] args) {
            new ServiceB(new ServiceA(new ServiceB()));
        }
    }
    
    如此,我们会发现这样会无限套娃。
    • set注入:可以实现循环依赖
    @Component
    public class ServiceAA {
    
        private ServiceBB serviceBB;
    
        public void setServiceBB(ServiceBB serviceBB) {
            this.serviceBB = serviceBB;
            System.out.println("ServiceAA 里设置了 ServiceBB");
        }
    
    }
    @Component
    public class ServiceBB {
    
        private ServiceAA serviceAA;
    
        public void setServiceAA(ServiceAA serviceAA) {
            this.serviceAA = serviceAA;
            System.out.println("ServiceBB 里设置了 ServiceAA");
        }
    }
    public class ClientSet {
        public static void main(String[] args) {
            ServiceAA serviceAA = new ServiceAA();
            ServiceBB serviceBB = new ServiceBB();
            serviceAA.setServiceBB(serviceBB);
            serviceBB.setServiceAA(serviceAA);
        }
    }
    
    运行结果:
    在这里插入图片描述
  3. Spring循环依赖
    • 默认的单例(Singleton)的场景是支持循环依赖的,不报错
    • 原型(Prototype)的场景是不支持循环依赖的,会报错
  4. Spring内部通过3级缓存来解决循环依赖(DefaultSingletonBeanRegistry)
    public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    protected static final Object NULL_OBJECT = new Object();
    protected final Log logger = LogFactory.getLog(this.getClass());
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);// 一级缓存
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);// 三级缓存
    private final Map<String, Object> earlySingletonObjects = new HashMap(16);// 二级缓存
    
    • 第一级缓存(也叫单例池)singletonObjects: 存放已经经历了完整生命周期的Bean对象
    • 第二级缓存 earlySingletonObjects: 存放早期暴露出来的Bean对象,Bean的生命周期未结束(属性还未填充完)
    • 第三级缓存 singletonFactories: 存放可以生成Bean的工厂
  5. 实例化/初始化
    • 实例化
      • 内存中申请一块内存空间(租赁好房子,自己的家具东西还没有搬家进去)
    • 初始化
      • 完成属性的各种赋值(装修,家电家具进场)
  6. refresh()方法就是加载Spring容器初始化的方法
    public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
        super(parent);
        this.setConfigLocations(configLocations);
        if (refresh) {
            this.refresh();// 这个
        }
    
    }
    
  7. 在Spring中那些以do开头的方法都是真正的业务逻辑方法(干实事的)
  8. 四大方法?
    • getSingleton(): 获取单例
    • doCreateBean(): 实例化Bean
    • populateBean(): 初始化Bean
    • addSingleton(): 将Bean添加到第一级缓存中,且从第三级缓存以及第二级缓存中删除。

Redis

  1. 什么是LRU算法?
    LRU是Least Recently Used的缩写,即最近最少使用,是一种常用的页面置换算法,选择最近最久未使用的数据予以淘汰。
  2. LRU算法思想:哈希+链表(HashMap + DoubleLinkedList)
    • 时间复杂度是O(1),哈希表+双向链表的结合体
  3. 巧用LinkedHashMap完成LRU算法
    public class LRUCacheDemo extends LinkedHashMap {
    
        private int capacity;
    
        public LRUCacheDemo(int capacity) {
            // Params:
            // initialCapacity – the initial capacity
            // loadFactor – the load factor
            // accessOrder – the ordering mode - true for access-order, false for insertion-order
            super(capacity, 0.75F, true);
            this.capacity = capacity;
        }
    
        @Override
        protected boolean removeEldestEntry(Map.Entry eldest) {
            return super.size() > capacity;
        }
    
        public static void main(String[] args) {
            LRUCacheDemo lruCacheDemo = new LRUCacheDemo(3);
            lruCacheDemo.put(1, "a");
            lruCacheDemo.put(2, "b");
            lruCacheDemo.put(3, "c");
            System.out.println(lruCacheDemo.keySet()); // [1, 2, 3]
    
            lruCacheDemo.put(4, "d");
            System.out.println(lruCacheDemo.keySet()); // [2, 3, 4]
            lruCacheDemo.put(3, "c");
            System.out.println(lruCacheDemo.keySet()); // [2, 4, 3]
            lruCacheDemo.put(3, "c");
            System.out.println(lruCacheDemo.keySet()); // [2, 4, 3]
            lruCacheDemo.put(3, "c");
            System.out.println(lruCacheDemo.keySet()); // [2, 4, 3]
            lruCacheDemo.put(5, "d");
            System.out.println(lruCacheDemo.keySet()); // [4, 3, 5]
        }
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值