02-手写模拟Spring底层原理
注意包名 看哪些是属于Spring源码中(package com.spring;) 哪些是应用spring的(package com.zhouyu;)
程序入口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| package com.zhouyu;
import com.spring.ZhouyuApplicationContext; import com.zhouyu.service.UserInterface; import com.zhouyu.service.UserService;
public class Test {
public static void main(String[] args) {
ZhouyuApplicationContext applicationContext = new ZhouyuApplicationContext(AppConfig.class);
UserInterface userService = (UserInterface) applicationContext.getBean("userService"); userService.test(); } }
|
AppConfig.class 所需要传入配置文件
1 2 3 4 5 6 7 8
| package com.zhouyu;
import com.spring.ComponentScan;
@ComponentScan("com.zhouyu.service") public class AppConfig { }
|
ComponentScan注解
1 2 3 4 5 6 7 8 9 10 11 12 13
| package com.spring;
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface ComponentScan {
String value() default ""; }
|
注解@Target和@Retention可以用来修饰注解,是注解的注解,称为元注解。
@Target : Target翻译中文为目标,即该注解可以声明在哪些目标元素之前,也可理解为注释类型的程序元素的种类。
ElementType.TYPE:该注解只能声明在一个类前。
ElementType.METHOD:该注解只能声明在一个类的方法前。
ElementType.FIELD:该注解只能声明在一个类的字段前。
@Retention :Retention 翻译成中文为保留,可以理解为如何保留,即告诉编译程序如何处理,也可理解为注解类的生命周期。
RetentionPolicy.SOURCE : 注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;
RetentionPolicy.CLASS : 注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期;
RetentionPolicy.RUNTIME : 注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;
这3个生命周期分别对应于:Java源文件(.java文件) —> .class文件 —> 内存中的字节码。
那怎么来选择合适的注解生命周期呢?
首先要明确生命周期长度 SOURCE < CLASS < RUNTIME ,所以前者能作用的地方后者一定也能作用。
ApplicationContext
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
| package com.spring;
import com.zhouyu.service.ZhouyuBeanPostProcessor;
import java.beans.Introspector; import java.io.File; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map;
public class ZhouyuApplicationContext {
private Class configClass; private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>(); private Map<String, Object> singletonObjects = new HashMap<>(); private List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>(); public ZhouyuApplicationContext(Class configClass) { this.configClass = configClass;
scan(configClass);
for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) { String beanName = entry.getKey(); BeanDefinition beanDefinition = entry.getValue(); if (beanDefinition.getScope().equals("singleton")) {
Object bean = createBean(beanName, beanDefinition); singletonObjects.put(beanName, bean);
} }
} private Object createBean(String beanName, BeanDefinition beanDefinition) { Class clazz = beanDefinition.getType();
Object instance = null; try {
instance = clazz.getConstructor().newInstance();
for (Field field : clazz.getDeclaredFields()) { if (field.isAnnotationPresent(Autowired.class)) {
field.setAccessible(true);
field.set(instance, getBean(field.getName())); } }
if (instance instanceof BeanNameAware) { ((BeanNameAware)instance).setBeanName(beanName); }
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) { instance = beanPostProcessor.postProcessBeforeInitialization(instance, beanName); }
if (instance instanceof InitializingBean) { ((InitializingBean)instance).afterPropertiesSet(); }
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) { instance = beanPostProcessor.postProcessAfterInitialization(instance, beanName); }
} catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); }
return instance; }
public Object getBean(String beanName) {
if (!beanDefinitionMap.containsKey(beanName)) { throw new NullPointerException(); }
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition.getScope().equals("singleton")) { Object singletonBean = singletonObjects.get(beanName); if (singletonBean == null) { singletonBean = createBean(beanName, beanDefinition); singletonObjects.put(beanName, singletonBean); } return singletonBean; } else { Object prototypeBean = createBean(beanName, beanDefinition); return prototypeBean; }
}
private void scan(Class configClass) { if (configClass.isAnnotationPresent(ComponentScan.class)) { ComponentScan componentScanAnnotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class); String path = componentScanAnnotation.value(); path = path.replace(".", "/");
ClassLoader classLoader = ZhouyuApplicationContext.class.getClassLoader(); URL resource = classLoader.getResource(path); File file = new File(resource.getFile());
if (file.isDirectory()) { for (File f : file.listFiles()) { String absolutePath = f.getAbsolutePath();
absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class")); absolutePath = absolutePath.replace("\\", ".");
try { Class<?> clazz = classLoader.loadClass(absolutePath);
if (clazz.isAnnotationPresent(Component.class)) {
if (BeanPostProcessor.class.isAssignableFrom(clazz)) { BeanPostProcessor instance = (BeanPostProcessor) clazz.getConstructor().newInstance(); beanPostProcessorList.add(instance); }
Component componentAnnotation = clazz.getAnnotation(Component.class); String beanName = componentAnnotation.value(); if ("".equals(beanName)) { beanName = Introspector.decapitalize(clazz.getSimpleName()); }
BeanDefinition beanDefinition = new BeanDefinition(); beanDefinition.setType(clazz);
if (clazz.isAnnotationPresent(Scope.class)) { Scope scopeAnnotation = clazz.getAnnotation(Scope.class); String value = scopeAnnotation.value(); beanDefinition.setScope(value); } else { beanDefinition.setScope("singleton"); }
beanDefinitionMap.put(beanName, beanDefinition); } } catch (ClassNotFoundException | NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); }
} }
} } }
|
Autowired注解
1 2 3 4 5 6 7 8 9 10 11 12 13
| package com.spring;
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Autowired {
}
|
Component注解
1 2 3 4 5 6 7 8 9 10 11 12 13
| package com.spring;
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Component {
String value() default ""; }
|
BeanPostProcessor 后置处理器接口
1 2 3 4 5 6 7 8 9 10 11 12
| package com.spring;
public interface BeanPostProcessor {
default Object postProcessBeforeInitialization(Object bean, String beanName) { return bean; }
default Object postProcessAfterInitialization(Object bean, String beanName) { return bean; } }
|
BeanDefinition类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| package com.spring;
public class BeanDefinition {
private Class type; private String scope; private boolean isLazy;
public Class getType() { return type; }
public void setType(Class type) { this.type = type; }
public String getScope() { return scope; }
public void setScope(String scope) { this.scope = scope; }
public boolean isLazy() { return isLazy; }
public void setLazy(boolean lazy) { isLazy = lazy; } }
|
InitializingBean接口
1 2 3 4 5
| package com.spring;
public interface InitializingBean { void afterPropertiesSet(); }
|
Scope注解
1 2 3 4 5 6 7 8 9 10 11 12 13
| package com.spring;
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Scope {
String value() default ""; }
|
BeanNameAware Aware回调接口
1 2 3 4 5 6
| package com.spring;
public interface BeanNameAware {
void setBeanName(String name); }
|
应用所写spring
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| package com.zhouyu.service;
import com.spring.*;
@Component public class UserService implements UserInterface, BeanNameAware {
@Autowired private OrderService orderService;
@ZhouyuValue("xxx") private String test;
private String beanName;
@Override public void setBeanName(String name) { this.beanName = name; }
public void test() { System.out.println(beanName); } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| package com.zhouyu.service;
import com.spring.Component;
@Component public class OrderService {
public void test() { System.out.println("test"); } }
|
jdk动态代理需要
1 2 3 4 5 6
| package com.zhouyu.service;
public interface UserInterface {
public void test(); }
|
实现AOP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| package com.zhouyu.service;
import com.spring.BeanPostProcessor; import com.spring.Component;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;
@Component public class ZhouyuBeanPostProcessor implements BeanPostProcessor {
@Override public Object postProcessAfterInitialization(Object bean, String beanName) {
if (beanName.equals("userService")) { Object proxyInstance = Proxy.newProxyInstance(ZhouyuBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("切面逻辑");
return method.invoke(bean, args); } });
return proxyInstance; }
return bean; } }
|
自定义注解
1 2 3 4 5 6 7 8 9 10 11 12 13
| package com.zhouyu.service;
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface ZhouyuValue {
String value() default ""; }
|
应用自定义注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| package com.zhouyu.service;
import com.spring.BeanPostProcessor; import com.spring.Component;
import java.lang.reflect.Field; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;
@Component public class ZhouyuValueBeanPostProcessor implements BeanPostProcessor {
@Override public Object postProcessBeforeInitialization(Object bean, String beanName) {
for (Field field : bean.getClass().getDeclaredFields()) { if (field.isAnnotationPresent(ZhouyuValue.class)) { field.setAccessible(true); try { field.set(bean, field.getAnnotation(ZhouyuValue.class).value()); } catch (IllegalAccessException e) { e.printStackTrace(); } } }
return bean; } }
|