手写一个简易版Spring框架源码
之前跟着周瑜老师手写了一个简易版spring,代码不多,通俗易懂,能帮大家更简单的理解spring底层实现
准备工作
先写一个spring项目基础的几个部分
启动测试类
package com.hong;
import com.hong.service.OrderService;
import com.spring.HongApplicationContext;
public class Test {
public static void main(String[] args) {
// 启动 spring
HongApplicationContext hongApplicationContext = new HongApplicationContext(AppConfig.class);
// getBean()
OrderService orderService = (OrderService) hongApplicationContext.getBean("orderService");
System.out.println(orderService);
}
配置类 AppConfig
package com.hong;
import com.spring.ComponmentScan;
@ComponmentScan("com.hong.service")
public class AppConfig {
}
业务层
OrderService
package com.hong.service;
import com.spring.Component;
@Component("userService")
public class UserService{
}
OrderService
package com.hong.service;
import com.spring.*;
@Component("orderService")
@Scope("prototype")
public class OrderService implements InitializingBean, BeanNameAware {
@AutoWired
private UserService userService;
private String beanName;
public void test() {
System.out.println(userService);
System.out.println("Aware="+beanName);
}
@Override
public void afterPropertiesSet() {
System.out.println("初始化");
}
@Override
public void setBeanName(String beanName) {
this.beanName = beanName;
}
}
基本注解
AutoWired
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,ElementType.METHOD,ElementType.CONSTRUCTOR})
public @interface AutoWired {
}
Component
实例化到spring容器中
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 "";
}
ComponentScan
作用就是根据定义的扫描路径,把符合扫描规则的类装配到spring容器中
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 ComponmentScan {
String value() default "";
}
Scope(作用域)
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Scope {
String value() default "singleton";
}
实现Spring的扫描逻辑
核心类
HongApplicationContext 核心接口或容器,允许容器通过应用程序上下文环境创建、获取、管理bean。为应用程序提供配置的中央接口
Class HongApplicationContext
private List<Class> scan(Class configClass) {
List<Class> classList = new ArrayList<>();
ComponmentScan componmentScan = (ComponmentScan) configClass.getAnnotation(ComponmentScan.class);
String scanPath = componmentScan.value(); // com.hong.service ----> com/hong/service
// 非懒加载的单例 @Lazy @Scope
// 生成单例bean---->单例池
scanPath = scanPath.replace(".","/");
// 如何扫描类
ClassLoader classLoader = HongApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(scanPath);
String s = null;
try {
s = URLDecoder.decode(resource.getFile(), "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
File file = new File(s); // 目录
// 指定的目录下的文件列表,可能是class,可能是txt
File[] files = file.listFiles();
for (File f : files) {
String absolutePath = f.getAbsolutePath();
absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"))
.replace("\", ".");
System.out.println("absolutePath="+absolutePath);
// class文件加载进来
try {
Class<?> clazz = classLoader.loadClass(absolutePath);
classList.add(clazz);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return classList;
}
@AutoWired注解的实现原理
spring bean的建模对象----BeanDefinition
bean的作用域,bean的注入模型,bean是否是懒加载等等信息,Class是无法抽象出来的,故而需要一个BeanDefinition类来抽象这些信息,以便于spring能够完美的实例化一个bean
package com.spring;
// 表示bean的定义
public class BeanDefinition {
private String scope;
private Class beanClass;
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public Class getBeanClass() {
return beanClass;
}
public void setBeanClass(Class beanClass) {
this.beanClass = beanClass;
}
}
核心类中扩展代码
private ConcurrentMap<String,BeanDefinition> beanDefinitionMap = new ConcurrentHashMap();
// 单例池
private ConcurrentHashMap<String,Object> singletonObjects = new ConcurrentHashMap();
public HongApplicationContext(Class configClass) {
// 扫描类
List<Class> classList = scan(configClass);
// 扫描到类了之后。解析这个类,Component,BeanDefinition(@Scope)
for (Class clazz : classList) {
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setBeanClass(clazz);
// if (clazz.isAnnotationPresent(Component.class)){}
Component component = (Component) clazz.getAnnotation(Component.class);
// 存在这个注解,证明就是个bean,拿到bean的名字
String beanName = component.value();
System.out.println("beanName="+beanName);
if (clazz.isAnnotationPresent(Scope.class)){
Scope scope = (Scope) clazz.getAnnotation(Scope.class);
beanDefinition.setScope(scope.value());
}else {
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName,beanDefinition);
}
for (String beanName : beanDefinitionMap.keySet()) {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition.getScope().equals("singleton")){
// 生成这个bean
Object bean = createBean(beanName,beanDefinition);
singletonObjects.put(beanName,bean);
}
}
// 生成单例bean(非懒加载) ---> 单例池
}
private Object createBean(String beanName,BeanDefinition beanDefinition) {
Class beanClass = beanDefinition.getBeanClass();
try {
// 实例化
Object bean = beanClass.getDeclaredConstructor().newInstance();
// 填充属性(依赖注入)
Field[] fields = beanClass.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(AutoWired.class)) {
// 拿到属性
Object userService = getBean(field.getName());
// 赋值
field.setAccessible(true);
field.set(bean,userService);
}
}
return bean;
}catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
public Object getBean(String beanName){
// 原型的话 判断是不是原型
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition.getScope().equals("prototype")){
return createBean(beanName,beanDefinition);
}else {
// 单例池中去拿
Object bean = singletonObjects.get(beanName);
if (bean == null){
Object o = createBean(beanName,beanDefinition);
singletonObjects.put(beanName,o);
return o;
}
return bean;
}
}
}
Spring中bean初始化原理
运行顺序
Spring IOC容器实例化Bean- 调用
BeanPostProcessor的postProcessBeforeInitialization方法 - 调用
bean实例的初始化方法 - 调用
BeanPostProcessor的postProcessAfterInitialization方法
InitializingBean
InitializingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候都会执行该方法。
package com.spring;
public interface InitializingBean {
public void afterPropertiesSet();
}
BeanNameAware接口
让Bean对Name或id有知觉
@AutoWired
private UserService userService;
private String beanName;
userService通过@AutoWired注解依赖注入,而beanName就需要实现BeanNameAware接口来赋值操作
package com.spring;
public interface BeanNameAware {
public void setBeanName(String beanName);
}
BeanPostProcessor
Spring IOC容器给我们提供的一个扩展接口,可以在对象初始化前后执行程序逻辑
public interface BeanPostProcessor {
//bean初始化方法调用前被调用
Object postProcessBeforeInitialization(Object bean, String beanName);
//bean初始化方法调用后被调用
Object postProcessAfterInitialization(Object bean, String beanName);
}
HongBeanPostProcessor
package com.hong.service;
import com.spring.BeanPostProcessor;
import com.spring.Component;
// @Component不仅仅代表@Bean的功能 是个组件
@Component
public class HongBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
System.out.println("初始化前");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
System.out.println("初始化后");
return bean;
}
}
HongApplicationContext完整逻辑代码
package com.spring;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public class HongApplicationContext {
private ConcurrentMap<String,BeanDefinition> beanDefinitionMap = new ConcurrentHashMap();
// 单例池
private ConcurrentHashMap<String,Object> singletonObjects = new ConcurrentHashMap();
// 扩展
private List<BeanPostProcessor> beanPostProcessorsList = new ArrayList<>();
public HongApplicationContext(Class configClass) {
// 扫描类
List<Class> classList = scan(configClass);
// 扫描到类了之后。解析这个类,Component,BeanDefinition(@Scope)
for (Class clazz : classList) {
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setBeanClass(clazz);
// if (clazz.isAnnotationPresent(Component.class)){}
Component component = (Component) clazz.getAnnotation(Component.class);
// 存在这个注解,证明就是个bean,拿到bean的名字
String beanName = component.value();
System.out.println("beanName="+beanName);
if (clazz.isAnnotationPresent(Scope.class)){
Scope scope = (Scope) clazz.getAnnotation(Scope.class);
beanDefinition.setScope(scope.value());
}else {
beanDefinition.setScope("singleton");
}
// clazz是不是BeanPostProcessor派生出来的
if (BeanPostProcessor.class.isAssignableFrom(clazz) ){
try {
BeanPostProcessor bpp = (BeanPostProcessor) clazz.getDeclaredConstructor().newInstance();
beanPostProcessorsList.add(bpp);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
beanDefinitionMap.put(beanName,beanDefinition);
}
for (String beanName : beanDefinitionMap.keySet()) {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition.getScope().equals("singleton")){
// 生成这个bean
Object bean = createBean(beanName,beanDefinition);
singletonObjects.put(beanName,bean);
}
}
// 生成单例bean(非懒加载) ---> 单例池
}
private Object createBean(String beanName,BeanDefinition beanDefinition) {
Class beanClass = beanDefinition.getBeanClass();
try {
// 实例化
Object bean = beanClass.getDeclaredConstructor().newInstance();
// 填充属性(依赖注入)
Field[] fields = beanClass.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(AutoWired.class)) {
// 拿到属性
Object userService = getBean(field.getName());
// 赋值
field.setAccessible(true);
field.set(bean,userService);
}
}
// Aware 新建一个接口 方法新加一个参数(扩展机制)
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
// 初始化之前 可以调用程序员定义的逻辑
for (BeanPostProcessor beanPostProcessor : beanPostProcessorsList) {
bean = beanPostProcessor.postProcessBeforeInitialization(bean, beanName);
}
// 初始化
if (bean instanceof InitializingBean) {
((InitializingBean)bean).afterPropertiesSet();
}
// 初始化之后 可以调用程序员定义的逻辑 可以aop
for (BeanPostProcessor beanPostProcessor : beanPostProcessorsList) {
bean = beanPostProcessor.postProcessAfterInitialization(bean,beanName);
}
return bean;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
public Object getBean(String beanName){
// 原型的话 判断是不是原型
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition.getScope().equals("prototype")){
return createBean(beanName,beanDefinition);
}else {
// 单例池中去拿
Object bean = singletonObjects.get(beanName);
if (bean == null){
Object o = createBean(beanName,beanDefinition);
singletonObjects.put(beanName,o);
return o;
}
return bean;
}
}
private List<Class> scan(Class configClass) {
List<Class> classList = new ArrayList<>();
ComponmentScan componmentScan = (ComponmentScan) configClass.getAnnotation(ComponmentScan.class);
String scanPath = componmentScan.value(); // com.hong.service ----> com/hong/service
// 非懒加载的单例 @Lazy @Scope
// 生成单例bean---->单例池
scanPath = scanPath.replace(".","/");
// 如何扫描类
ClassLoader classLoader = HongApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(scanPath);
String s = null;
try {
s = URLDecoder.decode(resource.getFile(), "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
File file = new File(s); // 目录
// 指定的目录下的文件列表,可能是class,可能是txt
File[] files = file.listFiles();
for (File f : files) {
String absolutePath = f.getAbsolutePath();
absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"))
.replace("\", ".");
System.out.println("absolutePath="+absolutePath);
// class文件加载进来
try {
Class<?> clazz = classLoader.loadClass(absolutePath);
classList.add(clazz);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return classList;
}
}