文章重要是走通spring核心原理,代码化繁为简,很多方法细节考虑不周全不用纠结
AnnotationConfigApplicationContext模仿spring源码中类AnnotationConfigApplicationContext
package com.spring;
import java.beans.Introspector;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author yanbing
* @version 1.0
* @date 2021/9/4 21:12
*/
public class AnnotationConfigApplicationContext implements ApplicationContext {
//存储bean定义信息,bean定义信息用途是生成bean对象
private ConcurrentHashMap<String, BeanDefinition> beanDefinitionConcurrentHashMap = new ConcurrentHashMap<>();
//已经初始化的单实例bean对象,全局唯一
private ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();
//所以的BeanPostProcessor的子类,在spring源码BeanPostProcessor是非常重要类,aop和类的扩展,@Value都是通过它类实现的
private List<BeanPostProcessor> beanPostProcessorList = new LinkedList<>();
/**
* spring 启动流程
*
* @param componentClasses
*/
public AnnotationConfigApplicationContext(Class<?> componentClasses) {
//扫描整个包, 得到BeanDefinition
scan(componentClasses);
//实例话非懒加载单列bean
// 1 实例化
// 2 属性赋值
// 3 Aare接口回调 @PostConstruct InitializingBean
// 4 初始化
// 5 添加到单实例缓存 singletonObjects
finishSingletonBeanInitialization();
}
private void finishSingletonBeanInitialization() {
for (String beanName : beanDefinitionConcurrentHashMap.keySet()) {
BeanDefinition beanDefinition = beanDefinitionConcurrentHashMap.get(beanName);
if (beanDefinition.getScope().equals(ScopeEnum.singleton)) {
Object bean = doCreateBean(beanName, beanDefinition);
singletonObjects.put(beanName, bean);
}
}
}
private Object doCreateBean(String beanName, BeanDefinition beanDefinition) {
Class beanClass = beanDefinition.getBeanClass();
try {
//构造函数实例化
Object instance = beanClass.getDeclaredConstructor().newInstance();
Field[] fields = beanClass.getDeclaredFields();
for (Field field : fields) {
//依赖注入
if (field.isAnnotationPresent(Autowired.class)) {
//真实spring源码通过属性的类型获取对象的,属性的名称可以随意命名
String filedName = field.getName();
Object bean = getBean(filedName);
field.setAccessible(true);
field.set(instance, bean);
}
}
//Aware回调
if (instance instanceof BeanNameAware) {
((BeanNameAware) instance).setBeanName(beanName);
}
//afterPropertiesSet回调
if (instance instanceof InitializingBean) {
((InitializingBean) instance).afterPropertiesSet();
}
//beanPostProcessor 初始化前处理
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessAfterInitialization(instance, beanName);
}
return instance;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
private void scan(Class<?> componentClasses) {
//获得需要扫描路径
ComponentScan componentClassesAnnotation = componentClasses.getAnnotation(ComponentScan.class);
String packagePath = componentClassesAnnotation.value();
if (packagePath.equals("")) {
throw new SpringException("packagePath cannot null ");
}
//获得AppClassLoader加载后的class(经过类的)
List<Class> beanList = getBeanClasses(packagePath);
//遍历beanClasses得到BeanDefinition
for (Class clazz : beanList) {
//只有类上加了注解Component才会生成BeanDefinition
if (clazz.isAnnotationPresent(Component.class)) {
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setBeanClass(clazz);
Component componentAnnotation = (Component) clazz.getAnnotation(Component.class);
String beanName = componentAnnotation.value();
if (beanName.equals("")) {
beanName = Introspector.decapitalize(clazz.getSimpleName());
}
//判断类是否为BeanPostProcessor父类,,然后添加到BeanPostProcessorList
if (BeanPostProcessor.class.isAssignableFrom(clazz)) {
try {
BeanPostProcessor beanPostProcessor = (BeanPostProcessor) clazz.getDeclaredConstructor().newInstance();
beanPostProcessorList.add(beanPostProcessor);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
//解析scope
if (clazz.isAnnotationPresent(Scope.class)) {
Scope scope = (Scope) clazz.getAnnotation(Scope.class);
String scopeValue = scope.value();
if (ScopeEnum.singleton.name().equals(scopeValue)) {
beanDefinition.setScope(ScopeEnum.singleton);
} else {
beanDefinition.setScope(ScopeEnum.prototype);
}
} else {
beanDefinition.setScope(ScopeEnum.prototype);
}
System.out.println("beanDefinition :" + beanDefinition.toString());
beanDefinitionConcurrentHashMap.put(beanName, beanDefinition);
}
}
}
private List<Class> getBeanClasses(String packagePath) {
/**
* 获得AppClassLoader加载器
* 加载过程经过:加载、验证、准备、解析
* 加载:在硬盘中查找并通过IO读入字节码文件至JVM虚拟机方法区,同时在堆中创建class对象
* 验证:校验字节码文件的正确性
* 准备:为类的静态变量分配内存,并将期初始化默认值。此阶段仅为静态变量(static修饰的字段变量)分配内存
* (例如static int=5 ,这里初始化值为0,5的赋值是在初始化时赋值);对于final static在编译的时候就已经分配了,
* 解析:把类中的符号引用转换为直接引用
*
*/
List<Class> beanClasses = new ArrayList<>();
ClassLoader classLoader = AnnotationConfigApplicationContext.class.getClassLoader();
packagePath = packagePath.replace(".", "/");
URL resource = classLoader.getResource(packagePath);
File file = new File(resource.getFile());
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File f : files) {
String fileName = f.getAbsolutePath();
if (fileName.endsWith(".class")) {
String className = fileName.substring(fileName.indexOf("com"), fileName.indexOf(".class"));
className = className.replace("\\", ".");
try {
Class<?> clazz = classLoader.loadClass(className);
beanClasses.add(clazz);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
for (Class beanClass : beanClasses) {
System.out.println("scan class :" + beanClass.toString());
}
} else {
throw new SpringException("packagePath cannot directory ");
}
return beanClasses;
}
@Override
public Object getBean(String beanName, Object... args) {
if (singletonObjects.containsKey(beanName)) {
return singletonObjects.get(beanName);
} else {
BeanDefinition beanDefinition = beanDefinitionConcurrentHashMap.get(beanName);
return doCreateBean(beanName, beanDefinition);
}
}
}
/**
* @author yanbing
* @version 1.0
* @date 2021/9/5 9:40
*/
public interface BeanPostProcessor {
/**
* 初始化前执行
* @param bean
* @param beanName
* @return
* @throws
*/
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
/**
* 初始化后执行
* @param bean
* @param beanName
* @return
* @throws
*/
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
@Component
public class YanibngBeanPostProcessor implements BeanPostProcessor {
public Object postProcessAfterInitialization(Object bean, String beanName) {
if ("orderService".equals(beanName)) {
System.out.println("postProcessAfterInitialization action ..............");
//使用jdk动态代理生成代理类,
Object proxy = Proxy.newProxyInstance(YanibngBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("aop 切面核心逻辑");
//此方法才是真实方法的执行
return method.invoke(bean, args);
}
});
return proxy;
}
return bean;
}
}
public class BeanDefinition {
private Class beanClass;
ScopeEnum scope;
public Class getBeanClass() {
return beanClass;
}
public void setBeanClass(Class beanClass) {
this.beanClass = beanClass;
}
public ScopeEnum getScope() {
return scope;
}
public void setScope(ScopeEnum scope) {
this.scope = scope;
}
@Override
public String toString() {
return "BeanDefinition{" +
"beanClass=" + beanClass +
", scope=" + scope +
'}';
}
}
public static void main(String[] args) {
ApplicationContext context=new AnnotationConfigApplicationContext(AppConfig.class);
OrderService bean = (OrderService) context.getBean("orderService");
bean.order();
}
@ComponentScan("com.yanbing.service")
public class AppConfig {
}
@Component("orderService")
public class OrderServiceimpl implements OrderService {
@Autowired
private UserServiceImpl userServiceImpl;
@Override
public void order() {
System.out.println("OrderServiceimpl order println .....................");
userServiceImpl.test();
}
}
@Component
@Scope()
public class UserServiceImpl implements BeanNameAware {
static int i=0;
static{
System.out.println("静态代码块...............");
}
{
System.out.println("代码块..............");
}
public void test() {
System.out.println("UserServiceImpl test println .....................");
}
@Override
public void setBeanName(String name) {
System.out.println("实现了BeanNameAware 接口 beanName:"+name);
}
}
scan class :interface com.yanbing.service.OrderService
scan class :class com.yanbing.service.OrderServiceimpl
scan class :class com.yanbing.service.UserServiceImpl
scan class :class com.yanbing.service.YanibngBeanPostProcessor$1
scan class :class com.yanbing.service.YanibngBeanPostProcessor
beanDefinition :BeanDefinition{beanClass=class com.yanbing.service.OrderServiceimpl, scope=prototype}
beanDefinition :BeanDefinition{beanClass=class com.yanbing.service.UserServiceImpl, scope=singleton}
beanDefinition :BeanDefinition{beanClass=class com.yanbing.service.YanibngBeanPostProcessor, scope=prototype}
静态代码块...............
代码块..............
实现了BeanNameAware 接口 beanName:userServiceImpl
postProcessAfterInitialization action ..............
aop 切面核心逻辑
OrderServiceimpl order println .....................
UserServiceImpl test println .....................
//获得需要扫描路径
ComponentScan componentClassesAnnotation = componentClasses.getAnnotation(ComponentScan.class);
String packagePath = componentClassesAnnotation.value();
if (packagePath.equals("")) {
throw new SpringException("packagePath cannot null ");
}
//中间略...............
//只有类上加了注解Component才会生成BeanDefinition
if (clazz.isAnnotationPresent(Component.class)) {
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setBeanClass(clazz);
Component componentAnnotation = (Component) clazz.getAnnotation(Component.class);
String beanName = componentAnnotation.value();
if (beanName.equals("")) {
beanName = Introspector.decapitalize(clazz.getSimpleName());
}
//判断类是否为BeanPostProcessor父类,,然后添加到BeanPostProcessorList
if (BeanPostProcessor.class.isAssignableFrom(clazz)) {
try {
BeanPostProcessor beanPostProcessor = (BeanPostProcessor) clazz.getDeclaredConstructor().newInstance();
beanPostProcessorList.add(beanPostProcessor);
} catch (Exception e) {
e.printStackTrace();
}
}
Field[] fields = beanClass.getDeclaredFields();
for (Field field : fields) {
//依赖注入
if (field.isAnnotationPresent(Autowired.class)) {
//真实spring源码通过属性的类型获取对象的,属性的名称可以随意命名
String filedName = field.getName();
Object bean = getBean(filedName);
field.setAccessible(true);
field.set(instance, bean);
}
}
//Aware回调
if (instance instanceof BeanNameAware) {
((BeanNameAware) instance).setBeanName(beanName);
}
//afterPropertiesSet回调
if (instance instanceof InitializingBean) {
((InitializingBean) instance).afterPropertiesSet();
}
public Object postProcessAfterInitialization(Object bean, String beanName) {
//我们这里简单化了,AOP源码做了大量工作识别类的方法是否需要切面
if ("orderService".equals(beanName)) {
System.out.println("postProcessAfterInitialization action ..............");
//使用jdk动态代理生成代理类,AOP中大部分对象都是通过cglib生成代理对象
Object proxy = Proxy.newProxyInstance(YanibngBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("aop 切面核心逻辑");
//此方法才是真实方法的执行
return method.invoke(bean, args);
}
});
return proxy;
}
return bean;
}