0%

声明式注入

@Configuration + @Bean

1
2
3
4
5
6
7
@Configuration
public class QuickstartConfiguration {
@Bean
public Person person() {
return new Person();
}
}

@Component + @ComponentScan

1
2
3
@Configuration
@ComponentScan("com.linkedbear.spring.annotation.c_scan")
public class ComponentScanConfiguration

@Import

1
2
@Import({Boss.class, BartenderConfiguration.class})
public @interface EnableTavern
阅读全文 »

SpringFramework 的事件模型

  • ApplicationEventPublisher:事件发布器,是用来接受事件,并交给事件广播器处理
  • ApplicationEventMulticaster:事件广播器,拿到事件发布器的事件,并广播给监听器

ApplicationContext 接口继承了 ApplicationEventPublisher ,拥有事件发布的功能;ApplicationContext 的第一个抽象实现类 AbstractApplicationContext 组合了一个 ApplicationEventMulticaster ,拥有事件广播的能力。综合来看,ApplicationContext 的落地实现就已经能够完成事件驱动模型中的 “观察者” 身份了

阅读全文 »

什么是SPI

SPI 全程叫 Service Provider Interface 服务提供接口,它可以通过一个指定的接口 / 抽象类,寻找到预先配置好的实现类(并创建实现类对象)。

Spring 通过 SpringFactoriesLoader 读取放在 META-INF 目录下名为 spring.factories 的文件,获取文件中的权限定类名转化为实体对象。

阅读全文 »

@Import

可直接导入普通类、配置类、ImportSeletor 的实现类和 ImportBeanDefinitionRegistrar 的实现类,通常情况下是写在自定义注解上

编写 ImportSeletor 的实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public interface ImportSelector {

/**
* Select and return the names of which class(es) should be imported based on
* the {@link AnnotationMetadata} of the importing @{@link Configuration} class.
* @return the class names, or an empty array if none
*/
String[] selectImports(AnnotationMetadata importingClassMetadata);

@Nullable
default Predicate<String> getExclusionFilter() {
return null;
}
}

通过 selectImports 方法导入对象,返回的是一组需要导入的类的全限定类名

阅读全文 »

BeanPostProcessor BeanFactoryPostProcessor BeanDefinitionRegistryPostProcessor
处理目标 bean 实例 BeanDefinition BeanDefinition、.class 文件等
执行时机 bena 的初始化阶段前后(已创建出 bean 对象) BeanDefinition解析完毕并注册进 BeanFactory 之后(此时 bean 未实例化) 配置文件、配置类已解析完毕并注册进 BeanFactory,但还未被 BeanFactoryPostProcessor 处理
可操作空间 对 bean 的属性赋值、创建代理对象等 给 BeanDefinition 中增删属性,移除 BeanDefinition 等 向 BeanFactory 中注册新的 BeanDefinition 和 BeanFactoryPostProcessor
阅读全文 »

@PostConstruct & @PreDestroy InitializingBean & DisposableBean init-method & destory-method
执行顺序 最先 中间 最后
组件耦合度 与 JSR 规范耦合 与 SpringFramework 耦合 无侵入(只有 <bean>@Bean 中使用)
容器支持 注解原生支持,xml需开启注解驱动 xml 、注解原生支持 xml 、注解原生支持
单实例Bean
原型Bean 只支持 init-method
阅读全文 »

代码、资料来自于马士兵MAC课程。

本文通过 strace 命令来监控使用 poll 和 epoll 不同模型的同一代码在内核方法调用上的不同。

阅读本文,你将切实体会到 poll 和 epoll 的不同实现方式。对于两种模型的介绍推荐阅读:网络IO-IO模型的演变

前置:如何用同一段代码使用 poll 和 epoll 两种不同模型

代码 Selector selector = Selector.open(); 在 poll 和 epoll 模型都支持的情况下优先选择 epoll。

可以通过 JVM 参数 -Djava.nio.channels.spi.SelectorProvider=sun.nio.ch.PollSelectorProvider 手动选择 poll 模型。

阅读全文 »

代码、资料来自于马士兵MAC课程。

本文主要讲解了IO模型,由 BIONIO,再演变到多路复用 select/pollepoll 的过程。

从本文中你可以了解到不同模型是如何解决之前模型所产生的问题,并且会带来什么样的新问题。

阅读全文 »

题目

leetcode第146题

运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制 。
实现 LRUCache 类:

  • LRUCache(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存
  • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
  • void put(int key, int value) 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
输入
["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
输出
[null, null, null, 1, null, -1, null, -1, 3, 4]

解释
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // 缓存是 {1=1}
lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
lRUCache.get(1); // 返回 1
lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
lRUCache.get(2); // 返回 -1 (未找到)
lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
lRUCache.get(1); // 返回 -1 (未找到)
lRUCache.get(3); // 返回 3
lRUCache.get(4); // 返回 4
阅读全文 »

学习马士兵课程-内存与IO,通过 netstatlsoftcpdump 观察tcp连接时内核在每一步都就行了什么相应的操作。

本文资料来自于马士兵MAC课程-内存与IO。

通过 netstat、lsof、tcpdump 观察 tcp 连接时内核在每一步都就行了什么相应的操作。

阅读本文,你可以知道在编写 java 代码时的每一步对应内核会产生哪些操作,其探究范围在客户端、服务端代码启动到客户端、服务端建立连接。

阅读全文 »