手写spring框架 (包含依赖注入,单例多例部分实现,spring常用注解用自定义注解实现)
代码文件结构
提示:以下是本篇文章正文内容,下面案例可供参考
一、实例代码
package com.spring.SpringHandWriting;
import lombok.Data;
@Data
public class BeanDefinition {
private Class type;
private String scope ;
private Boolean isLazy ;
}
package com.spring.SpringHandWriting;
@MyComponentScan("com.spring.SpringHandWriting")
public class MyAppConfig {
}
```java
package com.spring.SpringHandWriting;
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 MyComponent {
String value() default "";
}
package com.spring.SpringHandWriting;
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 MyComponentScan {
String value() default "";
}
package com.spring.SpringHandWriting;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
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.HashMap;
import java.util.Map;
public class MySpringContext {
private Class configClass;
private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
private Map<String, Object> singletonObjects = new HashMap<>();
public MySpringContext(Class<?> myAppConfigClass) {
this.configClass = myAppConfigClass;
//扫描 主要是扫描哪些对象被定义bean 加载配置信息到beanDefinitionMap
this.scan(configClass);
System.out.println(this.beanDefinitionMap);
//如果是单例模式 则创建对象 加入单例池
for( Map.Entry<String, BeanDefinition> key :beanDefinitionMap.entrySet()){
String beanName = key.getKey();
BeanDefinition beanDefinition = key.getValue();
if("singleton".equals(beanDefinition.getScope())){
Object bean = createBean(beanName, beanDefinition);
singletonObjects.put(beanName, bean);
}
}
}
private Object createBean(String beanName, BeanDefinition beanDefinition) {
Object instance = null;
Class clazz = beanDefinition.getType();
try {
instance = clazz.getConstructor().newInstance();
//依赖注入
for( Field field :clazz.getDeclaredFields()){
if(field.isAnnotationPresent(Autowired.class)){
//判断是否有成员变量有Autowired注解 如果有就生成bean注入
field.setAccessible(true);
field.set(instance,getBean(field.getName()));
}
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return instance;
}
private void scan(Class configClass) {
System.out.println(configClass);
MyComponentScan myComponentScan = (MyComponentScan) configClass.getAnnotation(MyComponentScan.class);
String path = myComponentScan.value().replace(".", "/");
ClassLoader classLoader = configClass.getClassLoader();
URL resource = classLoader.getResource(path);
File file = new File(resource.getFile());
if (file.isDirectory()) {
for (File f : file.listFiles()) {
String absolutePath = f.getPath();
absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"));
absolutePath = absolutePath.replace("\\", ".");
try {
Class clazz = classLoader.loadClass(absolutePath);
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setType(clazz);
String beanName = "";
//如果有component注解 说明是bean加入map
if(clazz.isAnnotationPresent(MyComponent.class)){
beanName = Introspector.decapitalize(clazz.getSimpleName());
System.out.println(beanName);
//判断scope 注解 如果是为空就默认是单例
if(clazz.isAnnotationPresent(Scope.class)){
Scope scopeAnnotation = (Scope) clazz.getAnnotation(Scope.class);
String value = scopeAnnotation.value();
if(StringUtils.isBlank(value)){
value = "singleton";
}
beanDefinition.setScope(value);
}
beanDefinitionMap.put(beanName, beanDefinition);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
public Object getBean(String beanName) {
//如果beanDefinitionMap 说明没有当前的bean配置
if (!beanDefinitionMap.containsKey(beanName)) {
throw new NullPointerException();
}
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
//spring默认是单例bean
if ("singleton".equals(beanDefinition.getScope())||beanDefinition.getScope()==null) {
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;
}
}
}
package com.spring.SpringHandWriting;
import org.springframework.stereotype.Component;
@MyComponent("orderService")
public class OrderService {
}
package com.spring.SpringHandWriting;
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 "";
}
package com.spring.SpringHandWriting;
public class SptingMain {
public static void main(String[] args) {
MySpringContext mySpringContext = new MySpringContext(MyAppConfig.class);
UserService o = (UserService) mySpringContext.getBean("userService");
System.out.println(o);
System.out.println(o.getOrderService());//依赖注入对象
}
}
package com.spring.SpringHandWriting;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
@Data
@Scope("singleton")
@MyComponent("userService")
public class UserService {
@Autowired
private OrderService orderService;
}