Spring 就像是我们写代码的一个管家,可能我们在项目中要创建对象,要写单例多例,要加日志,要加事务等等很多功能点。那这些东西如果能有一个现有的框架那就好了,它就是Spring,它不但实现了以上的功能,并且集成容纳各种其他的开源框架。

    自己手写Spring的核心就是springbean的生成。

    1:通过包扫描 获取到哪些类需要加载到spring容器中,加载到spring中到底是单例还是多例。
    2:单例是从单例池(map)中获取,非单例就是每次getBean的时候重新的创建一个新的对象。
    3:因为只有包的名称,所以要通过获取包下面的file来获取file的名称以及全路径,从而通过classload把class信息加载到beanDefinition中

    核心代码

    1. public ConcurrentHashMap<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();
    2. public ConcurrentHashMap<String, Object> singleObjects = new ConcurrentHashMap<String, Object>();
    3. public AnnotationConfigApplicationContext(Class clazz){
    4. //1:通过给的类 获取到需要加载的bean的位置
    5. scan(clazz);
    6. //2.加载到容器
    7. instanceSingleBean();
    8. }
    9. private void instanceSingleBean(){
    10. try {
    11. //1:获取beanDefinitionMap 封装的类信息
    12. for (String beanName : beanDefinitionMap.keySet()){
    13. BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
    14. if("singleton".equals(beanDefinition.getScope())){
    15. Object bean = doCreateBean(beanDefinition);
    16. singleObjects.put(beanName, bean);
    17. }
    18. }
    19. }catch (Exception e){
    20. e.printStackTrace();
    21. }
    22. }
    23. private Object doCreateBean(BeanDefinition beanDefinition) throws Exception{
    24. Class clazz = beanDefinition.getBeanClass();
    25. Object bean = clazz.getDeclaredConstructor().newInstance();
    26. Field[] fields = clazz.getDeclaredFields();
    27. for (Field field : fields){
    28. String beanName = field.getName();
    29. if(field.isAnnotationPresent(Autowried.class)){
    30. Object fieldBean = getBean(beanName);
    31. field.setAccessible(true);
    32. field.set(bean, fieldBean);
    33. }
    34. }
    35. return bean;
    36. }
    37. private void scan(Class clazz) {
    38. //1:获取当前类的注解 找到需要扫描的包的路径
    39. ComponentScan scan = (ComponentScan)clazz.getAnnotation(ComponentScan.class);
    40. String packagePath = scan.value();
    41. //获取当前包下的所有的类
    42. List<Class> packageClass = genBeanClasses(packagePath);
    43. //2:把类封装为BeanDefinition的map
    44. toMap(packageClass);
    45. }
    46. private void toMap(List<Class> packageClass) {
    47. for (Class clazz : packageClass){
    48. if(clazz.isAnnotationPresent(Service.class)){
    49. //通过当前clazz封装BeanDefinition
    50. BeanDefinition beanDefinition = new BeanDefinition();
    51. beanDefinition.setBeanClass(clazz);
    52. Service service = (Service) clazz.getAnnotation(Service.class);
    53. String beanName = service.value();
    54. if(clazz.isAnnotationPresent(Scope.class)){
    55. Scope scope = (Scope) clazz.getAnnotation(Scope.class);
    56. String scopeValue = scope.value();
    57. if("prototype".equals(scopeValue)){
    58. beanDefinition.setScope("prototype");
    59. }else{
    60. beanDefinition.setScope("singleton");
    61. }
    62. }
    63. beanDefinitionMap.put(beanName, beanDefinition);
    64. }
    65. }
    66. }
    67. /**
    68. * 通过com.mkb.server -> com/mkb/service 再拼接上 类的全路径 得到file文件 通过file文件 获取到文件名 就是 service名称
    69. * 然后通过 classLoader.loadClass(className); 获取到class 集合
    70. */
    71. private List<Class> genBeanClasses(String packagePath) {
    72. List<Class> beanClasses = new ArrayList<Class>();
    73. ClassLoader classLoader = AnnotationConfigApplicationContext.class.getClassLoader();
    74. packagePath = packagePath.replace(".", "/");
    75. URL resource = classLoader.getResource(packagePath);
    76. File file = new File(resource.getFile());
    77. if (file.isDirectory()) {
    78. File[] files = file.listFiles();
    79. for (File f : files) {
    80. String fileName = f.getAbsolutePath();
    81. if (fileName.endsWith(".class")) {
    82. String className = fileName.substring(fileName.indexOf("com"), fileName.indexOf(".class"));
    83. className = className.replace("\\", ".");
    84. try {
    85. Class<?> clazz = classLoader.loadClass(className);
    86. beanClasses.add(clazz);
    87. } catch (ClassNotFoundException e) {
    88. e.printStackTrace();
    89. }
    90. }
    91. }
    92. }
    93. return beanClasses;
    94. }
    95. public Object getBean(String beanName) throws Exception{
    96. if(!beanDefinitionMap.containsKey(beanName)){
    97. throw new Exception();
    98. }
    99. BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
    100. if("singleton".equals(beanDefinition.getScope())){
    101. return singleObjects.get(beanName);
    102. }else{
    103. return doCreateBean(beanDefinition);
    104. }
    105. }

    码云地址:https://gitee.com/EraserMei/simple-spring.git