1 前置知识
非懒加载的单例bean:spring容器启动时就创建
懒加载的单例bean:.getBean()时再创建 @Lazy
原型(多例)bean:每次 getBean时都创建,@Scope("prototype")
2 代码模拟
2.1 基础框架
模拟spring容器:
public class ApplicationContext {
private Class configClass;
public ApplicationContext(Class configClass) {
this.configClass = configClass;
}
public Object getBean(String beanName){
return null;
}
}
模拟@ComponentScan:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScan {
String value() default "";
}
@Retention注解:修饰注解的注解,表示注解的生命周期;RunTime表示运行时去动态获取注解信息
@Target注解:表示注解作用的范围;type = 接口、类、枚举、注解
模拟@Component:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
String value() default "";
}
2.2 spring源码分析
spring容器在创建的时候,如何知道哪些单例bean需要创建?
扫描@ComponentScan下所有的单例bean
spring项目最终会打包,如何找到@ComponentScan对应的路径?
通过类加载器,相对路径 -> 打包后的绝对路径;最后找到文件
ClassLoader classLoader = ApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path);
File file = new File(resource.getFile());
spring为何要创建BeanDefinition?
方便记录Bean的所有信息
为何要有BeanDefinitionMap<String,BeanDefinition>?
将扫描后Bean的信息记录在BeanDefinitionMap中,方便后续创建bean
为何要有BeanPostProcessor?
spring提供该接口,是为了实现初始化前、初始化后的逻辑;实现该接口的类需要标注@Component注解、且重写Before、After两个方法;在扫描的时候,添加到容器中,在创建Bean的时候调用
2.3 spring核心源码
public class ApplicationContext {
private Class configClass;
private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>(16);
private Map<String,Object> singletonObjects = new HashMap<>(16);
private List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();
public ApplicationContext(Class configClass) {
this.configClass = configClass;
//扫描
scan(configClass);
//创建bean
for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
String beanName = entry.getKey();
if ("".equals(beanName)){
beanName = Introspector.decapitalize(aClass.getSimpleName());
}
BeanDefinition beanDefinition = entry.getValue();
if (beanDefinition.getScope().contains("singleton")){
Object bean = createBean(beanName, beanDefinition);
singletonObjects.put(beanName,bean);
}else{
}
}
}
}
扫描:
private void scan(Class configClass) {
//判断是否存在ComponentScan注解
if (configClass.isAnnotationPresent(ComponentScan.class)) {
ComponentScan componentScanAnnotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class);
//获取扫描路径
String path = componentScanAnnotation.value();
path = path.replace(".", "/"); //com/liuxin/service
//需要根据此路径,找到编译后的路径
ClassLoader classLoader = ApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path); //通过path相对路径,找到编译后的路径
//获取指定路径下的所有文件
File file = new File(resource.getFile());
if (file.isDirectory()) {
for (File f : file.listFiles()) {
String absolutePath = f.getAbsolutePath();
//判断文件是否包含@Component注解
//将文件加载为class对象
absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"));
absolutePath = absolutePath.replace("\\", ".");
BeanDefinition beanDefinition = new BeanDefinition();
try {
Class<?> aClass = classLoader.loadClass(absolutePath);
if (aClass.isAnnotationPresent(Component.class)) {
//判断是否实现了BeanPostProcessor
if (BeanPostProcessor.class.isAssignableFrom(aClass)){
BeanPostProcessor instance = (BeanPostProcessor) aClass.getConstructor().newInstance();
beanPostProcessorList.add(instance);
}
//说明是Bean
Component componentAnnotation = aClass.getAnnotation(Component.class);
String beanName = componentAnnotation.value();
if ("".equals(beanName)) {
beanName = Introspector.decapitalize(aClass.getSimpleName());
}
//判断是单例bean还是多例,多例bean不在此处加载
if (aClass.isAnnotationPresent(Scope.class)) {
Scope scopeAnnotation = aClass.getAnnotation(Scope.class);
String scope = scopeAnnotation.value();
beanDefinition.setScope(scope);
//...
} else {
//单例
beanDefinition.setScope("singleton");
}
beanDefinition.setType(aClass);
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();
}
}
}
}
}
创建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);
String name = field.getName();
field.set(instance, getBean(name));
}
}
//初始化前
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
beanPostProcessor.postProcessBeforeInitialization(beanDefinition,beanName);
}
//初始化
if (instance instanceof InitializingBean){
((InitializingBean) instance).afterPropertiesSet();
}
//初始化后
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
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;
}
获取Bean:
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 bean = createBean(beanName, beanDefinition);
return bean;
}
}
BeanPostProcessor:
public interface BeanPostProcessor {
default Object postProcessBeforeInitialization(Object bean,String beanName){
return bean;
}
default Object postProcessAfterInitialization(Object bean,String beanName){
return bean;
}
}
@Component
public class LiuxinBeanPostProcessor 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("初始化后");
Object instance = Proxy.newProxyInstance(LiuxinBeanPostProcessor.class.getClassLoader()
, bean.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return null;
}
});
return instance;
}
}