目录
1.自动扫描bean注入
2.getBean
3.实现依赖注入
4.实现AOP功能
码云地址: https://gitee.com/xzc_1033426945/alibabacloud.git
通过仿写spring一方面可以更好体会领悟其设计思想,理解设计模式,另一方面可以更好的理解spring本身的底层原理 先实现主干功能,再完善细节扩展点的顺序编写 持续更新
扩大1.自动扫描bean注入
经典入口重写实现
/**
* @author xzc
*/
public class Test {
public static void main(String[] args) {
XzcApplicationContext applicationContext = new XzcApplicationContext(XzcAppConfig.class);
UserInterface userService = (UserInterface) applicationContext.getBean("userService");
userService.test();
}
}
1.自定义标签的写法 new选择标签
自定义sacn标签
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentXzcScan {
String value() default "";
}
配置标签
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ConfigurationXzc {
}
显然我们需要重写的内容围绕写一个自己的context 和自己config配置类
初步重写context构造方法
private Class configClass;
private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
private Map<String, Object> singletonObjects = new HashMap<>();
private List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();
/**
* 首先梳理主流程
* 1.构造方法创建context 入参为配置类
* 2.解析配置类信息做bean扫描
* 3.创建单例Bean
* 4.BeanDefinition
* 5.BeanPostPRocess
*/
public XzcApplicationContext(Class configClass) {
this.configClass = configClass;
// 解析配置类信息做bean扫描
scan(configClass);
}
写扫描bean的scan方法 先判断标签是否齐全 有config 和 scan标签
/**
* 解析配置类信息做bean扫描
* 1.扫描判断传入类是否有有我们自定义注解@ComponentXzcScan的类 有进入 没有跳过
*
* @param configClass
*/
private void scan(Class configClass) {
System.out.println("scan configClass" + configClass);
if (configClass.isAnnotationPresent(ConfigurationXzc.class)) {
if (configClass.isAnnotationPresent(ComponentXzcScan.class)) {
ComponentXzcScan componentScanAnnotation = (ComponentXzcScan) configClass.getAnnotation(ComponentXzcScan.class);
scanComponentXzcScan(componentScanAnnotation);
}
}
}
标签齐全 执行扫描方法 递归扫描class文件 解析出获得beanDefinition存入 beanDefinitionMap
这之前需要 先自定义一个极简单的beanDefinition
/**
* @Author: xzc
* @Date: 2021/9/4 21:11
* @Version 1.0
*/
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;
}
}
配套标签@ScopeXzc
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ScopeXzc {
String value() default "";
}
其实实现scanComponentXzcScan
/**
* 1.拿传入ComponentXzcScan类的 包扫描路径
* 2.拿appClassLoader的类加载器
* 3.类加载器按照包扫描路径 去扫描字节码文件
*
* 3.1 找有@ComponentXzc标签的类 解析出beanDefinition 放入beanDefinitionMap
*
* @param componentScanAnnotation
*/
private void scanComponentXzcScan(ComponentXzcScan componentScanAnnotation) {
String path = componentScanAnnotation.value();
path = path.replace(".", "/");
ClassLoader appClassLoader = XzcApplicationContext.class.getClassLoader();
URL resource = appClassLoader.getResource(path);
String f1 = resource.getFile();
File file = new File(f1);
/**3.1 类加载器按照包扫描路径 去扫描加载字节码文件 */
if (file.isDirectory()) {
for (File f : file.listFiles()) {
try {
String absolutePath = f.getAbsolutePath();
absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"));
absolutePath = absolutePath.replace("\", ".");
Class<?> clazz = appClassLoader.loadClass(absolutePath);
/**
* 3.2 如果加载到ComponentXzc标签的类
*/
if (clazz.isAnnotationPresent(ComponentXzc.class)) {
/**
* 3.21 clazz解析出填充该bean的beanDefinition属性 并放入beanDefinitionMap中
*/
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setType(clazz);
if (clazz.isAnnotationPresent(ScopeXzc.class)) {
ScopeXzc scopeXzc = clazz.getAnnotation(ScopeXzc.class);
String value = scopeXzc.value();
beanDefinition.setScope(value);
} else {
beanDefinition.setScope("singleton");
}
ComponentXzc componentAnnotation = clazz.getAnnotation(ComponentXzc.class);
String beanName = componentAnnotation.value();
if ("".equals(beanName)) {
beanName = Introspector.decapitalize(clazz.getSimpleName());
}
beanDefinitionMap.put(beanName, beanDefinition);
/**
* 3.22 clazz调用构造方法创建实例放入 后置处理器beanPostProcessorList中
*/
if (BeanPostProcessor.class.isAssignableFrom(clazz)) {
BeanPostProcessor instance = (BeanPostProcessor) clazz.getConstructor().newInstance();
beanPostProcessorList.add(instance);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
有了 beanDefinitionMap 回到原来的构造方法 我们可以在写ioc容器了
/**
* 首先梳理主流程
* 1.构造方法创建context 入参为配置类
* 2.解析配置类信息做bean扫描
* 3.BeanDefinition
* 4.创建单例Bean的单例池 singletonObjects
* 5.BeanPostPRocess
*/
public XzcApplicationContext(Class configClass) {
this.configClass = configClass;
// 解析配置类信息做bean扫描
scan(configClass);
/**
* beanDefinitionMap 我们就可以写单例池了
*/
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);
}
}
}
有了beanname beanDefinition 来创建creatBean
/**
* 根据beanDefinition创建bean
* @param beanName
* @param beanDefinition
* @return
*/
private Object createBean(String beanName, BeanDefinition beanDefinition) {
Class clazz = beanDefinition.getType();
Object instance = null;
try {
instance = clazz.getConstructor().newInstance();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return instance;
}
2.getBean
/**
* 获取bean
* 1.先去beanDefinitionMap里面拿有没有beanName对应的BeanDefinition
* 2,如果有取出来判断是否为单例
* 3.返回 bean
*
* @param beanName
* @return
*/
public Object getBean(String beanName) {
if (beanDefinitionMap.containsKey(beanName)) {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
/**
* 2.1如果为单例 去单例池拿 如果没有 就调creatbean创建一份 放入 再返回
*/
if (beanDefinition.getScope().equals("singleton")) {
Object singletonBean = singletonObjects.get(beanName);
if (singletonBean == null) {
singletonBean = createBean(beanName, beanDefinition);
singletonObjects.put(beanName, singletonBean);
}
return singletonBean;
}
/**
* 2.2如果为原型 直接调createBean创建一份
*/
else if (beanDefinition.getScope().equals("prototype")) {
// 原型
Object prototypeBean = createBean(beanName, beanDefinition);
return prototypeBean;
} else {
System.out.println("只考虑单例多例 其他 未完待续");
}
} else {
System.out.println("这个Bean 未定义");
}
return null;
}
试一把
@ComponentXzc
@ScopeXzc(value = "singleton")
public class UserService implements UserInterface{
@Override
public void test() {
System.out.println("UserService test");
}
}
一个最基本可用的spring context就实现了
3.实现依赖注入
先定义标签@AutowiredXzc 这里的ElementType.FIELD
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface AutowiredXzc {
String value() default "";
}
重写我们的getBean方法 添循环扫描字段标签@AutowiredXzc的 扫到调getBean注入
(递归 spring循环依赖问题就在这里了)
/**
* 根据beanDefinition创建bean
* @param beanName
* @param beanDefinition
* @return
*/
private Object createBean(String beanName, BeanDefinition beanDefinition) {
Class clazz = beanDefinition.getType();
Object instance = null;
try {
instance = clazz.getConstructor().newInstance();
/**
* 1.for循环遍历字段找到字段里的@AutowiredXzc标签
* 2.调用getBean方法去拿bean注入
* 这里是一个递归 就是spring经典的循环依赖问题了
*/
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(AutowiredXzc.class)) {
field.setAccessible(true);
field.set(instance, getBean(field.getName()));
}
}
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessAfterInitialization(instance, beanName);
}
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return instance;
}
添加例子
@ComponentXzc
@ScopeXzc(value = "singleton")
public class OrderService{
void test(){
System.out.println("OrderService test");
}
}
在userService里面注入OrderService
@ComponentXzc
//@ScopeXzc(value = "singleton")
@ScopeXzc(value = "prototype")
public class UserService implements UserInterface{
@Autowired
OrderService orderService;
@Override
public void test() {
System.out.println("UserService test");
orderService.test();
}
}
依赖注入成功
存在的问题循环依赖
未完待续
4.实现AOP功能
首先我们定义后置处理器