我们前面分析很多的Spring源码,现在我们来手写一个简易的Spring源码
创建一个maven工程。
public class Test {
? ?public static void main(String[] args) {
? ? ? ?AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
? ? ? ?UserService userService = context.getBean("UserService", UserService.class);
? ? ? ?userService.test();
? }
}
在我们的通常Spring项目中,一定有这几步,我们想要手写就得先模拟出这几个方法和类。
Autowrite注解的依赖注入实现: 遍历出类中的所有属性,循环他们进行判断是否加了Autowrite注解,通过getBean得到对象,再把得到的对象赋值给instance。(记得开启Accessible)
创建一个扫描注解?创建bean注解??一个scope判断是否是单例注解??在启动类上配置扫描注解,给扫描路径???创一个Annotationcontext类??有get?bean方法。通过得到注解扫描的类,通过App扫描得到注解所需要扫描的地址,通过截取?替换路径,解析成为com.user.service字符串,把他放入到classloader.loadclass中得到class对象?判断对象上是否有component注解,得到当前bean对应的名字????(创建beandefinition描述类??里面有?scope??class属性?)设置bd的class属性为当前类属性????判断当前类是否有原型bean注解??没有就设置它的描述scope为单例??有就设置它为注解上的值?????最后将它们放入beandefinitionmap中????????当我们在getbean的时候??传入beanName?我们在bdMap中去找???找到了则进行判断是否为单例bean??是则直接返回这里返回的bean对象都是一样的,称之为单例bean?????不是则通过bd中的class类通过反射进行创建,这里每创建的bean都是不一样的???不存在就抛出异常?????当然spring在启动的时候就把bean对象创建好了??我们通过循环bad.enteyset??得到bean名字和bd??判断是否是单例的,是就直接放入单例池。
package com.spring;
?
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.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
?
public class LuoChaoApplicationContext {
?
?
? //对应AppConfig.class
? private Class configClass;
?
? //单例池 存放单例bean 确保我们得到得对象都是单例的。
? private ConcurrentHashMap<String,Object> singletonObjects = new ConcurrentHashMap<>();
?
? //存放BeanDefintion对象的HashMap
? private ConcurrentHashMap<String,BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
?
? //存放BeanPostProcessor集合
? private List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();
?
? public LuoChaoApplicationContext(Class configClass) {
? ? ? this.configClass = configClass;
?
? ? ? //解析配置类
? ? ? // Compontent注解---》扫描路径---》扫描---》BeanDefinition---》beanDefinitionMap
? ? ? sacn(configClass);
?
? ? ? //在我们启动的时候就要把所有的单例bean创建好
? ? ? /*
? ? ? entrySet()的返回值也是返回一个Set集合,此集合的类型为Map.Entry。
? ? ? ? Map.Entry是Map声明的一个内部接口,此接口为泛型,定义为Entry<K,V>。
? ? ? ? 它表示Map中的一个实体(一个key-value对)。接口中有getKey(),getValue方法。
? ? ? ? */
? ? ? for (Map.Entry<String,BeanDefinition> entry : beanDefinitionMap.entrySet()) {
? ? ? ? ? //得到bean的名字
? ? ? ? ? String beanName = entry.getKey();
? ? ? ? ? BeanDefinition beanDefinition = entry.getValue();
? ? ? ? ? //判断是否是单例bean
? ? ? ? ? if (beanDefinition.getScope().equals("singleton")){
? ? ? ? ? ? ? Object bean = createBean(beanName,beanDefinition);
? ? ? ? ? ? ? //是单例的把它放到单例池里面去
? ? ? ? ? ? ? singletonObjects.put(beanName,bean);
? ? ? ? ? }
? ? ? }
?
?
? }
?
? //对应getBean方法
? public Object getBean(String beanName){
? ? ? //判断传进来的这个名字有没有对应的bean描述
? ? ? if (beanDefinitionMap.containsKey(beanName)){
? ? ? ? ? BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
? ? ? ? ? //判断名字对象的对象是否是单例的
? ? ? ? ? if (beanDefinition.getScope().equals("singleton")){
? ? ? ? ? ? ? //从单例池中拿到这个对象
? ? ? ? ? ? ? Object o = singletonObjects.get(beanName);
? ? ? ? ? ? ? return o;
? ? ? ? ? }else {
? ? ? ? ? ? ? //原型bean 创建bean对象。
? ? ? ? ? ? ? Object bean = createBean(beanName,beanDefinition);
? ? ? ? ? ? ? return bean;
? ? ? ? ? }
?
? ? ? }else {
? ? ? ? ? //不存在
? ? ? ? ? throw new NullPointerException();
? ? ? }
?
? }
?
?
? // 通过beanDefinition描述创建一个对象
? public Object createBean(String beanName ,BeanDefinition beanDefinition){
? ? ? //得到bean的class对象
? ? ? Class clazz = beanDefinition.getClazz();
? ? ? //通过反射调用无参构造进行bean的创建
? ? ? try {
? ? ? ? ? Object instance = clazz.getDeclaredConstructor().newInstance();
?
? ? ? ? ? //依赖注入 (不考虑循环依赖问题)
? ? ? ? ? // 得到类中的属性
? ? ? ? ? Field[] declaredFields = clazz.getDeclaredFields();
?
? ? ? ? ? for (Field declaredField : clazz.getDeclaredFields()) {
? ? ? ? ? ? ? //判断是否加了自动注入注解。
? ? ? ? ? ? ? if (declaredField.isAnnotationPresent(Autowired.class)){
? ? ? ? ? ? ? ? ? //此处我们先只判断byName 我们调用getBean得到对象
? ? ? ? ? ? ? ? ? Object bean = getBean(declaredField.getName());
? ? ? ? ? ? ? ? ? //判断required是否为false
? ? ? ? ? ? ? ? ? Autowired annotation = declaredField.getAnnotation(Autowired.class);
? ? ? ? ? ? ? ? ? boolean required = annotation.required();
? ? ? ? ? ? ? ? ? //判断bean为空并且required值为false 无法注入值
? ? ? ? ? ? ? ? ? if (bean==null && required){
? ? ? ? ? ? ? ? ? ? ? //抛出异常
? ? ? ? ? ? ? ? ? ? ? throw new RuntimeException();
? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? //实际上setAccessible是启用和禁用访问安全检查的开关
? ? ? ? ? ? ? ? ? declaredField.setAccessible(true);
? ? ? ? ? ? ? ? ? // 将bean对象赋值给instance属性。
? ? ? ? ? ? ? ? ? declaredField.set(instance,bean);
? ? ? ? ? ? ? }
? ? ? ? ? }
?
? ? ? ? ? //判断是否实现了BeanNameAware接口 也叫做回调
? ? ? ? ? ? ? if (instance instanceof BeanNameAware){
? ? ? ? ? ? ? ? ? ((BeanNameAware) instance).setBeanName(beanName);
? ? ? ? ? ? ? }
?
? ? ? ? ? ? ? //遍历出所有存放的beanPostProcessor
? ? ? ? ? ? ? for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
? ? ? ? ? ? ? ? ? //将对象和名字传入 进行初始化前的操作
? ? ? ? ? ? ? ? ? instance = beanPostProcessor.postProcessBeforeInitialization(instance,beanName);
? ? ? ? ? ? ? }
?
? ? ? ? ? ? ? //判断是否实现了InitializingBean接口 ? 初始化
? ? ? ? ? ? ? if (instance instanceof InitializingBean){
? ? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? ? ((InitializingBean) instance).afterPropertiesSet();
? ? ? ? ? ? ? ? ? } catch (Exception e) {
? ? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? }
?
? ? ? ? ? ? ? //遍历出所有存放的beanPostProcessor
? ? ? ? ? ? ? for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
? ? ? ? ? ? ? ? ? //将对象和名字传入 进行初始化后的操作
? ? ? ? ? ? ? ? ? instance = beanPostProcessor.postProcessAfterInitialization(instance,beanName);
? ? ? ? ? ? ? }
?
? ? ? ? ? ? ? //BeanPostProcessor
?
? ? ? ? ? //直接返回创建的bean对象
? ? ? ? ? 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 sacn(Class configClass) {
? ? ? //拿到配置类进行解析
? ? ? //解析ComponentScan注解拿到扫描路径进行扫描
? ? ? ComponentScan componentScanAnnotation = (ComponentScan) configClass.getDeclaredAnnotation(ComponentScan.class);
? ? ? //拿到注解扫描得路径
? ? ? String path = componentScanAnnotation.value();
?
? ? ? //进行扫描类上面是否加载了ComponentScan注解
? ? ? /**
? ? ? ? * Bootstrap---》jre/lib
? ? ? ? * ext----》jre/ext/lib
? ? ? ? * App----》classpath
? ? ? ? */
? ? ? ClassLoader classLoader = LuoChaoApplicationContext.class.getClassLoader();//得到得就是app
? ? ? URL resource = classLoader.getResource("com/luochao/service");
? ? ? //得到service目录
? ? ? File file = new File(resource.getFile());
? ? ? //判断是不是一个目录
? ? ? if (file.isDirectory()){
? ? ? ? ? File[] files = file.listFiles();
? ? ? ? ? for (File file1 : files) {
? ? ? ? ? ? ? //E:\code\springBychaoluo\target\classes\com\luochao\service\UserService.class
? ? ? ? ? ? ? System.out.println(file1.getAbsolutePath());
?
? ? ? ? ? ? ? /*
? ? ? ? ? ? ? 利用类加载加载class对象
? ? ? ? ? ? ? 我们要需要得不是所有得路径,我们只需要com.luochao.service.UserService路径
? ? ? ? ? ? ? 所以我们进行分解路径
? ? ? ? ? ? ? ? */
? ? ? ? ? ? ? String fileName = file1.getAbsolutePath();
? ? ? ? ? ? ? //判断是.class文件才进行截取替换
? ? ? ? ? ? ? if (fileName.endsWith(".class")){
? ? ? ? ? ? ? ? ? String className = fileName.substring(fileName.indexOf("com"), fileName.indexOf(".class"));
? ? ? ? ? ? ? ? ? //com.luochao.service.UserService
? ? ? ? ? ? ? ? ? className = className.replace("\\", ".");
? ? ? ? ? ? ? ? ? System.out.println(className);
?
? ? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? ? Class<?> aClass = classLoader.loadClass(className);
? ? ? ? ? ? ? ? ? ? ? //判断类上是否有Component注解
? ? ? ? ? ? ? ? ? ? ? if (aClass.isAnnotationPresent(Component.class)){
? ? ? ? ? ? ? ? ? ? ? ? ? //表示当前这个类是一个bean
? ? ? ? ? ? ? ? ? ? ? ? ? //解析类,判断当前bean是单例bean,还是原型bean 还是prototype的bean
? ? ? ? ? ? ? ? ? ? ? ? ? // BeanDefinition bean的定义
?
? ? ? ? ? ? ? ? ? ? ? ? ? //扫描到了LuoChaoBeanPostProcessor进行是否有实现BeanPostProcessor
? ? ? ? ? ? ? ? ? ? ? ? ? //判断当前的aclass是否实现了BeanPostProcessor接口
? ? ? ? ? ? ? ? ? ? ? ? ? if (BeanPostProcessor.class.isAssignableFrom(aClass)){
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //利用反射得到对象 在spring是使用getBean的方法执行的 使得在BeanPostProcessor中我们也可以自动注入bean对象 但是这里我们就用简单的办法容易理解。
// ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? String name = aClass.getName();
// ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? BeanPostProcessor instance = (BeanPostProcessor) getBean(name);
// ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? beanDefinitionMap.put(name,beanDefinition);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? BeanPostProcessor instance = (BeanPostProcessor) aClass.getDeclaredConstructor().newInstance();
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //存放到集合中
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? beanPostProcessorList.add(instance);
? ? ? ? ? ? ? ? ? ? ? ? ? }
?
? ? ? ? ? ? ? ? ? ? ? ? ? Component componentAnnotation = aClass.getDeclaredAnnotation(Component.class);
? ? ? ? ? ? ? ? ? ? ? ? ? //当前bean类所对应的名字
? ? ? ? ? ? ? ? ? ? ? ? ? String beanName = componentAnnotation.value();
?
? ? ? ? ? ? ? ? ? ? ? ? ? //表示bean的一个定义
? ? ? ? ? ? ? ? ? ? ? ? ? BeanDefinition beanDefinition = new BeanDefinition();
? ? ? ? ? ? ? ? ? ? ? ? ? //给beandefinition类的class属性设置值为当前类属性
? ? ? ? ? ? ? ? ? ? ? ? ? beanDefinition.setClazz(aClass);
?
? ? ? ? ? ? ? ? ? ? ? ? ? //判断是否存在scope注解
? ? ? ? ? ? ? ? ? ? ? ? ? if (aClass.isAnnotationPresent(Scope.class)){
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //原型bean
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Scope scopeAnnotation = aClass.getDeclaredAnnotation(Scope.class);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? beanDefinition.setScope(scopeAnnotation.value());
? ? ? ? ? ? ? ? ? ? ? ? ? }else {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //单例bean 设置它对应的描述为单例的
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? beanDefinition.setScope("singleton");
? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? //存放拿到的beanName
? ? ? ? ? ? ? ? ? ? ? ? ? beanDefinitionMap.put(beanName,beanDefinition);
? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? } catch (ClassNotFoundException e) {
? ? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? ? } catch (InstantiationException e) {
? ? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? ? } catch (InvocationTargetException e) {
? ? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? ? } catch (NoSuchMethodException e) {
? ? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? ? } catch (IllegalAccessException e) {
? ? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? }
? ? ? ? ? }
? ? ? }
? }
?
?
?
}
public class BeanDefinition {
?
? //bean的类型
? private Class clazz;
? //是否是原型bean
? private String scope;
?
?
? public Class getClazz() {
? ? ? return clazz;
? }
?
? public void setClazz(Class clazz) {
? ? ? this.clazz = clazz;
? }
?
? public String getScope() {
? ? ? return scope;
? }
?
? public void setScope(String scope) {
? ? ? this.scope = scope;
? }
}
//Bean的描述类
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.METHOD,ElementType.FIELD})
public @interface Autowired {
? String value() default "";
?
? boolean required() default true;
}
?回调
package com.spring;
?
//回调
public interface BeanNameAware {
?
? void setBeanName(String name);
}
package com.spring;
?
//AOP的最终归宿
public interface BeanPostProcessor {
?
? //初始化前
? Object postProcessBeforeInitialization(Object bean, String beanName);
?
? //初始化后
? Object postProcessAfterInitialization(Object bean, String beanName);
?
?
}
?
package com.spring;
?
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
?
//生成bean注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
? String value() default "";
}
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 ComponentScan {
?
? String value();
}
package com.spring;
?
//初始化
public interface InitializingBean {
?
? void afterPropertiesSet() throws Exception;
}
?
package com.spring;
?
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
?
//原型bean标签
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Scope {
? String value();
?
? //单例bean是指我们在测试类中通过getbean多次得到得对象是同一个 原型bean得到得则是不同得对象
}
package com.luochao.service;
?
?
import com.spring.BeanPostProcessor;
import com.spring.Component;
?
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
?
?
//将具体的AOP代理逻辑封装成一个LuoChaoBeanPostProcessor放入Spring容器中
@Component
public class LuoChaoBeanPostProcessor implements BeanPostProcessor {
?
? @Override
? public Object postProcessBeforeInitialization(Object bean, String beanName) {
? ? ? if (beanName.equals("userService")){
? ? ? ? ? System.out.println("初始化前");
? ? ? ? ? ((UserService)bean).setBeanName("我是帅哥");
? ? ? }
? ? ? return bean;
? }
?
? @Override
? public Object postProcessAfterInitialization(Object bean, String beanName) {
? ? ? System.out.println("初始化后");
? ? ? //模拟简易的AOP 这里就可以判断是否要aop
? ? ? if (beanName.equals("userService")){
? ? ? ? ? /*
? ? ? ? ? JDK动态代理生成一个代理对象
? ? ? ? ? 在spring源码中 开启Aop就是在Spring容器中生成一个BeanPostProcessor的Bean对象
? ? ? ? ? ? 放到Spring容器中去
? ? ? ? ? ? */
? ? ? ? ? Object proxyInstance = Proxy.newProxyInstance(LuoChaoBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
? ? ? ? ? ? ? ? ? //找到jionpoint 切点
? ? ? ? ? ? ? ? ? System.out.println("AOP代理逻辑");
? ? ? ? ? ? ? ? ? // 执行bean中的方法进行代理
? ? ? ? ? ? ? ? ? return method.invoke(bean,args);
? ? ? ? ? ? ? }
? ? ? ? ? });
? ? ? ? ? //代理对象
? ? ? ? ? return proxyInstance;
? ? ? }
? ? ? return bean;
? }
}
package com.luochao.service;
?
import com.spring.Component;
?
@Component("peopleService")
public class PeopleService {
?
?
}
package com.luochao.service;
?
public interface UserService {
?
? void test();
?
? void setBeanName(String beanName);
}
package com.luochao.service;
?
import com.spring.Autowired;
import com.spring.Component;
import com.spring.InitializingBean;
?
?
@Component("userService")
public class UserServiceImpl implements UserService {
?
? @Autowired
? private PeopleService peopleService;
?
? private String beanName;
?
? public void setBeanName(String beanName) {
? ? ? this.beanName = beanName;
? }
?
? // Aware 回调
? // ? @Override
? // ? public void setBeanName(String name) {
? // ? ? ? beanName = name;
? // ? }
?
? public void test(){
? ? ? System.out.println(peopleService);
? ? ? System.out.println(beanName);
? }
?
?
// ? //初始化
// ? @Override
// ? public void afterPropertiesSet() throws Exception {
// ? ? ? System.out.println("初始化");
// ? }
}
?
package com.luochao;
?
import com.spring.ComponentScan;
?
// 扫描启动类
@ComponentScan("com.luochao.service")
public class AppConfig {
}
?
package com.luochao;
?
import com.luochao.service.UserService;
import com.luochao.service.UserServiceImpl;
import com.spring.LuoChaoApplicationContext;
?
public class Test {
?
? public static void main(String[] args) {
? ? ? LuoChaoApplicationContext luoChaoApplicationContext = new LuoChaoApplicationContext(AppConfig.class);
? ? ? UserService userService = (UserService) luoChaoApplicationContext.getBean("userService");
? ? ? userService.test();
? ? ? //1.代理对象 ? 2.业务test
?
? }
}
至此我们模拟了Spring的扫描bean 并且注入bean 简易的Aop 简易的回调 还有单例池。后面继续完善。
迈出这一小步,一定能跨上山巅。
?
|