SpringBoot源码
效果:加入springBoot注解后,在run方法中传入application.class就能实现自动启动并匹配到对象的controller返回结果。
-
导入Spring依赖 -
定义注解(在自己的应用Apllication加入该注解,作为SpringBoot项目启动),注解上加入@ComponentScan。当应用添加后,相当于添加@ComponentScan注解在自己的类上,就会默认扫描自己包下的所有文件,就可以扫描到controller文件夹下的文件。 -
自定义Run方法,并在其中启动tomcat -
添加DispatchServlet(SpringMVC),需要接受一个spring容器,因为DispathServlet是在该容器中找对应的Controller. -
添加Spring容器,需要传入一个配置类
Spring源码
基础准备
使用Spring框架时,用到的创建语句
public class MiaoboApplicationContext {
Class configClass;
public MiaoboApplicationContext(Class configClass){
this.configClass = configClass;
}
public Object getBean(){
return null;
}
}
定义ApplicationContext类,定义需要填入的配置文件属性以及getBean方法
public class MiaoboApplicationContext {
Class configClass;
public MiaoboApplicationContext(Class configClass){
this.configClass = configClass;
}
public Object getBean(){
return null;
}
}
用户的配置类添加@ComponentScan,自定义@ComponentScan,定义属性指定扫描路径
@ComponentScan("com.miaobo.service")
public class AppConfig {
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScan {
String value();
}
Service类添加@Component注解表示定义的Bean,自定义@Component
@Component("userService")
public class UserService {
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
String value();
}
基础完成后,Application需要在初始化后解析配置类,通过@ComponentScan扫描带有@Component
扫描
获取扫描路径,并通过类加载器得到所有该路径下的文件
Class configClass;
public MiaoboApplicationContext(Class configClass) throws ClassNotFoundException {
this.configClass = configClass;
ComponentScan componentScanAnnotation = (ComponentScan) configClass.getDeclaredAnnotation(ComponentScan.class);
String path = componentScanAnnotation.value();
path = path.replace(".","/");
ClassLoader configClassLoader = MiaoboApplicationContext.class.getClassLoader();
URL resource = configClassLoader.getResource(path);
File directory = new File(resource.getFile());
if(directory.isDirectory()){
File[] files = directory.listFiles();
for(File file: files){
System.out.println(file);
}
}
}
在获取到的文件中寻找带有@Component注解的类。即先根据包名得到所有的类,再判断是否有@Component注解。
if(directory.isDirectory()){
File[] files = directory.listFiles();
for(File file: files){
String fileName = file.getAbsolutePath();
if (fileName.endsWith(".class")) {
fileName = fileName.substring(fileName.indexOf("com"), fileName.indexOf(".class"));
fileName = fileName.replace("\\", ".");
Class<?> clazz = configClassLoader.loadClass(fileName);
if (clazz.isAnnotationPresent(Component.class)) {
System.out.println("yes");
}
}
}
}
实例化Bean(单例/原型)
getBean方法中需要通过传入的BeanName去寻找类的信息(困难),因此在ApplicationContex初始化时就创建每个Bean的BeanDefinition对象(包含类信息、是否单例等)。
HashMap singlePool = new HashMap<String, Object>();
ConcurrentHashMap beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();
发现@Component后,需要判断是否为原型Bean或单例Bean。添加@Scope(“Prototype”)表示原型Bean。单例就直接创建Bean放入单例池。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Scope {
String value();
}
if (clazz.isAnnotationPresent(Component.class)) {
Component componentAnnotation = clazz.getDeclaredAnnotation(Component.class);
String beanName = componentAnnotation.value();
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setClazz(clazz);
Scope scopeAnnotation = clazz.getDeclaredAnnotation(Scope.class);
if (scopeAnnotation.value().equals("prototype")) {
beanDefinition.setScope("prototype");
}
else {
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName, beanDefinition);
}
将放入扫描包—》所有类均创建对应BeanDefinition——》放入BeanDefinitionMap,提取成一个Scan方法。并对BeanDefinition中原型Bean进行创建并放入单例池。
scan(configClass);
for(Map.Entry<String, BeanDefinition> entry: beanDefinitionMap.entrySet()){
String beanName = entry.getKey();
BeanDefinition beanDefinition = entry.getValue();
if (beanDefinition.getScope().equals("singleton")) {
Object o = createBean(beanName);
singlePool.put(beanName, o);
}
}
getBean从BeanDefinitionMap取BeanDefinition,如果为单例就去查找单例池。
public Object getBean(String beanName) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
if (beanDefinitionMap.containsKey(beanName)) {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition.getScope().equals("singleton")) {
Object o = singlePool.get(beanName);
return o;
}
else {
return createBean(beanName);
}
}
else {
throw new NullPointerException();
}
}
初始化以及getBean中均用到createBean方法
private Object createBean(String BeanName) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
BeanDefinition beanDefinition = beanDefinitionMap.get(BeanName);
Class clazz = beanDefinition.getClazz();
Object o = clazz.getConstructor().newInstance();
return o;
}
依赖注入
createBean中:找到所有属性-》查看具有@Autowored注解的
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Autowired {
}
private Object createBean(String BeanName) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
BeanDefinition beanDefinition = beanDefinitionMap.get(BeanName);
Class clazz = beanDefinition.getClazz();
Object o = clazz.getConstructor().newInstance();
for (Field declaredField : clazz.getDeclaredFields()) {
if (declaredField.isAnnotationPresent(Autowired.class)) {
declaredField.setAccessible(true);
Object bean = getBean(declaredField.getName());
declaredField.set(o, bean);
}
}
return o;
}
}
Aware回调
需要实现注入String BeanName属性值,模仿BeanNameAware接口
接口创建
public interface BeanNameAware {
public void setBeanName(String name);
}
需要自动获得BeanName的类实现该接口
@Component("userService")
@Scope("prototype")
public class UserService implements BeanNameAware {
@Autowired
private OrderService orderService;
String BeanName;
public void test(){
System.out.println(orderService);
}
@Override
public void setBeanName(String name) {
this.BeanName = name;
}
}
createBean方法中判断是否实现接口,是则将BeanName赋予
if (o instanceof BeanNameAware) {
BeanNameAware beanNameAware = (BeanNameAware) o;
beanNameAware.setBeanName(BeanName);
}
下列代码,测试结果为:com.miaobo.service.OrderService@533ddba userService
public class Test {
public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
MiaoboApplicationContext applicationContext = new MiaoboApplicationContext(AppConfig.class);
UserService userService = (UserService) applicationContext.getBean("userService");
userService.test();
System.out.println(userService.BeanName);
}
}
初始化(类似Aware)
实现接口,内部由程序员决定功能
public interface InitializingBean {
public void afterPropertiesSet();
}
@Component("userService")
@Scope("prototype")
public class UserService implements BeanNameAware, InitializingBean {
@Autowired
private OrderService orderService;
public String BeanName;
public void test(){
System.out.println(orderService);
}
@Override
public void setBeanName(String name) {
this.BeanName = name;
}
@Override
public void afterPropertiesSet() {
System.out.println("初始化");
}
}
createBean中判断接口实现,并执行afterPropertiesSet()
if (o instanceof InitializingBean) {
InitializingBean initializingBean = (InitializingBean) o;
initializingBean.afterPropertiesSet();
}
BeanPostProcessor
针对所有Bean(如果针对某个Bean可以在方法中判断),在Bean的创建过程添砖加瓦。不同于判断接口的方式,而是直接将实现类加入容器中,在容器中判断是否Bean需要BeanPostProcessor方法。
定义接口(此处实现初始化前后的BeanPostProcessor)
public interface BeanPostProcessor {
Object postProcessorBeforeInitializing(Object bean, String beanName);
Object postProcessorAfterInitializing(Object bean, String beanName);
}
程序员实现接口,并自定义方法。将该实现类注册为Bean
@Component("miaoboBeanPostProcessor")
@Scope("prototype")
public class MiaoboBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessorBeforeInitializing(Object bean, String beanName) {
System.out.println("初始化前");
if (beanName.equals("userService")) {
((UserService)bean).setName("小狗");
}
return bean;
}
@Override
public Object postProcessorAfterInitializing(Object bean, String beanName) {
System.out.println("初始化后");
return bean;
}
}
ApplicationContext初始化过程中,判断容器中是否有类实现了接口,并将其存入列表(存入列表示因为可能有多个BeanPostProcess的实现类,这些类中的方法都是需要在初始化前后进行添加的操作,创建一个Bean就需要将所有BeanPostProcess所有实现类执行完)。
if (BeanPostProcessor.class.isAssignableFrom(clazz)) {
BeanPostProcessor beanPostProcessor = (BeanPostProcessor) clazz.getDeclaredConstructor().newInstance();
beanPostProcessorArrayList.add(beanPostProcessor);
}
在类的创建过程中运行BeanPostProcessor实现的方法(所有Bean都会有)
}
for (BeanPostProcessor beanPostProcessor : beanPostProcessorArrayList) {
beanPostProcessor.postProcessorBeforeInitializing(o, beanName);
}
if (o instanceof InitializingBean) {
InitializingBean initializingBean = (InitializingBean) o;
initializingBean.afterPropertiesSet();
}
for (BeanPostProcessor beanPostProcessor : beanPostProcessorArrayList) {
beanPostProcessor.postProcessorAfterInitializing(o, beanName);
}
Aop
初始化后的方法中进行aop,即postProcessorAfterInitializing()方法中。不同于BeanPostProcess针对Bean的生产过程前后的添砖加瓦,aop针对某个方法执行前后进行。
由于jdk的动态代理基于接口,因此创建需要实现aop类的接口对象
public interface UserServiceInterface {
public void test();
}
@Component("userService")
@Scope("prototype")
public class UserService implements BeanNameAware, InitializingBean, UserServiceInterface{...}
DisapthServlet源码
通过url直接能返回页面
SpringStater源码
管理相关依赖,读取配置
模块1:业务项目:spring-boot-hello
package com.hello.service;
public class TestService {
}
模块2:自动配置依赖:spring-boot-autoconfiguration-hello
-
导入辅助依赖spring-boot-autoconfiguration, spring-boot-autoconfiguration-processor <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.7.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure-processor</artifactId>
<optional>true</optional>
<version>2.7.3</version>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>spring-boot-hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
-
配置属性编写,导入该starter后,可以读取编写的默认的属性:hello.xxxx=10 package com.hello;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("hello.word")
public class helloProperties {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
-
配置类编写,可以返回创建好的对象 @Configuration(proxyBeanMethods = false)
@ConditionalOnClass(TestService.class)
@EnableConfigurationProperties(helloProperties.class)
@ConditionalOnWebApplication
public class helloAutoConfiguration {
@Resource
helloProperties properties;
Logger logger = Logger.getLogger(this.getClass().getName());
@Bean
@ConditionalOnMissingBean
public TestService testService(){
logger.info("自定义stater启动");
logger.info("或取的默认属性值"+properties.getValue());
return new TestService();
}
}
-
创建resourse/META-INF/spring.factories,与自己编写的autoConfiguration挂钩,spring会扫描spring.factories文件并自动配置 org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.hello.helloAutoConfiguration
模块3:启动器(删除src,只进行包管理):spring-boot-starter-hello
<dependency>
<groupId>com.example</groupId>
<artifactId>spring-boot-autoconfiguration-hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
删除root项目pom.xml中的打包依赖,lifecycle/install安装到本地后,在另外的项目导入自编写starter
HashMap源码
定义HashMap,以及put/get方法
public class TestHashMap<K, V> {
final static int arrayCapacity = 8;
ArrayList<Map.Entry> arrayList = new ArrayList(arrayCapacity);
public Map.Entry get(){
return null;
}
public void put(K k, V v){
return;
}
public void transform(){
return;
}
public static void main(String[] args) {
HashMap<Integer, String> integerStringHashMap = new HashMap<>();
integerStringHashMap.put(1, "小明");
integerStringHashMap.put(2, "小芳");
System.out.println(integerStringHashMap.get(1));
}
}
定义链表节点
public class ListNode<K, V> implements Map.Entry<K, V>{
K key;
V value;
ListNode<K, V> next;
public ListNode(K key, V value, ListNode<K, V> next) {
this.key = key;
this.value = value;
this.next = next;
}
@Override
public K getKey() {
return this.key;
}
@Override
public V getValue() {
return this.value;
}
@Override
public V setValue(V value) {
this.value = value;
return this.value;
}
}
定义二叉树节点
class TreeNode<K, V> implements Map.Entry<K, V>{
TreeNode<K, V> left;
TreeNode<K,V> right;
K key;
V value;
TreeNode(K key, V value, TreeNode<K, V> left, TreeNode<K, V> right){
this.key = key;
this.value = value;
this.left = left;
this.right = right;
}
@Override
public K getKey() {
return this.key;
}
@Override
public V getValue() {
return this.value;
}
@Override
public V setValue(V value) {
this.value = value;
return this.value;
}
}
定义二叉树
class AVL<K, V> implements Map.Entry {
int size=0;
TreeNode head;
public AVL(int size) {
this.size = size;
}
public void insert(K k, V v){
TreeNode newTreeNode = new TreeNode<>(k, v, null, null);
if(this.size==0){
head = newTreeNode;
}
else {
TreeNode cur = head;
TreeNode parent = head;
while (cur!=null){
if(cur.key.hashCode()<=newTreeNode.key.hashCode()){
parent=cur;
cur = cur.left;
}
else {
parent = cur;
cur = cur.right;
}
}
if(parent.key.hashCode()>newTreeNode.key.hashCode()){
parent.left=newTreeNode;
}
else {
parent.right = newTreeNode;
}
}
size++;
return;
}
public V get(K k){
if(size==0){return null;}
TreeNode ptr = this.head;
while (ptr!=null){
if(ptr.key.hashCode()==k.hashCode()){
return (V) ptr.value;
} else if (ptr.key.hashCode()<k.hashCode()) {
ptr=ptr.left;
}
else {
ptr=ptr.right;
}
}
return null;
}
@Override
public Object getKey() {
return null;
}
@Override
public Object getValue() {
return null;
}
@Override
public Object setValue(Object value) {
return null;
}
}
put方法,java源码中的put方法包含数组扩容(负载因子默认0.75)。当数组大小大于64,链表大于8时,将链表转换为红黑树。此处省略扩容,当链表长度大于8是就转换链表为红黑树。
public void put(K k, V v){
ListNode newNode = new ListNode(k, v, null);
int index = k.hashCode() % arrayCapacity;
if(arrayList.get(index) ==null){
arrayList.set(index, newNode);
}
else {
int flag = 0;
ListNode head = (ListNode)arrayList.get(index);
ListNode cur=head;
while (cur.next!=null){
cur = cur.next;
flag++;
if (flag>=8) {
if(arrayList.get(index).getClass()==AVL.class){
AVL<K, V> avl = new AVL<>(0);
cur = head;
while (cur!=null){
avl.insert((K)cur.key, (V)cur.value);
}
avl.insert(k, v);
arrayList.set(index, avl);
}
else {
AVL<K, V> avl = (AVL<K, V>) arrayList.get(index);
avl.insert(k, v);
}
return;
}
}
cur.next = newNode;
}
return;
}
get方法
public V get(K k){
int index = k.hashCode()%arrayCapacity;
Map.Entry head = arrayList.get(index);
if(head.getClass()==ListNode.class){
ListNode listHead = (ListNode)head;
while (listHead!=null){
if(listHead.key==k){
return (V)listHead.value;
}
listHead = listHead.next;
}
return null;
}
else {
AVL avl = (AVL)head;
return (V) avl.get(k);
}
}
ConcurrentHashMap源码
不再像1.7给segment上锁,而是给每个节点上锁,当添加元素时:
节点处为空:cas+valite创建节点
if(arrayList.get(index) ==null){
ListNode newNode = new ListNode(k, v, null);
do {
if(arrayList.get(index) ==null)
arrayList.set(index, newNode);
break;
}while (arrayList.get(index) ==null);
}
节点处不为空:锁住,添加元素
else synchronized (arrayList.get(index)){...}
|