手写Spring3.x以上

一.准备工作

1.创建maven项目

2.创建配置类,加载容器类,启动类

 

 

复制代码
public class CharkeyApplicationContext {

    private Class appConfig;

    public CharkeyApplicationContext(Class appConfig) {
        this.appConfig = appConfig;
    }

    public Object getBean(String name) {
       return null;
    }
}
复制代码
public class Application {

    public static void main(String[] args) {
        CharkeyApplicationContext chakeyApplicationContext = new CharkeyApplicationContext(AppConfig.class);
        Object bean1 = chakeyApplicationContext.getBean("userService");
        System.out.println(bean1);
    }
}

 二.IOC之扫描加载Bean对象

1.添加扫描Config类注解compentScan

2.添加compent注解标注扫描类

3.Bean加载到容器中

4.调用getBean

 

复制代码
package annotiton;

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Component {

    String value() default "";
}
复制代码
复制代码
package annotiton;

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ComponentScan {

    String value();
}
复制代码
复制代码
package annotiton;

public class BeanDefinition {

    private Class clazz;

    private String scope;//单例 多例

    public BeanDefinition() {
    }

    public BeanDefinition(Class clazz, String scope) {
        this.clazz = clazz;
        this.scope = 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;
    }
}
复制代码
@Component("orderService")
public class OrderServiceImpl implements OrderService {
}
@Component("userService")
public class UserServiceImpl implements UserService {


}
package config;

import annotiton.ComponentScan;

@ComponentScan("service.impl")
public class AppConfig {
}
复制代码
package spring;

import annotiton.BeanDefinition;
import annotiton.Component;
import annotiton.ComponentScan;

import java.io.File;
import java.net.URL;
import java.util.concurrent.ConcurrentHashMap;

public class CharkeyApplicationContext {

    private Class appConfig;

    private static ConcurrentHashMap<String, BeanDefinition> beanDifinitionMap = new ConcurrentHashMap<>();

    public CharkeyApplicationContext(Class configClass) {
        this.appConfig = appConfig;

        //扫描bean
        scan(configClass);
    }

    public Object getBean(String name) {
        BeanDefinition beanDefinition = beanDifinitionMap.get(name);
        return beanDefinition;
    }

    public void scan(Class app) {

        boolean annotationPresent = app.isAnnotationPresent(ComponentScan.class);
        if (!annotationPresent) throw new RuntimeException("没有配置类");

        ComponentScan componentScan = (ComponentScan) app.getDeclaredAnnotation(ComponentScan.class);
        String path = componentScan.value();
        System.out.println(path);

        ClassLoader classLoader = CharkeyApplicationContext.class.getClassLoader();
        path = path.replace(".", "/");
        System.out.println(path);
        URL resource = classLoader.getResource("service/impl");//"com/charkey/service"
        File file = new File(resource.getFile());
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (int i = 0; i < files.length; i++) {
                File file1 = files[i];
                String absolutePath = file1.getAbsolutePath();
                System.out.println(absolutePath);
                absolutePath = absolutePath.substring(absolutePath.indexOf("service"), absolutePath.indexOf(".class"));
                System.out.println(absolutePath);
                absolutePath = absolutePath.replace("\\", ".");
                System.out.println(absolutePath);

                Class<?> clazz = null;
                try {
                    clazz = classLoader.loadClass(absolutePath);

                    boolean isComponent = clazz.isAnnotationPresent(Component.class);
                    if (!isComponent) continue;
                    Component declaredAnnotation = clazz.getDeclaredAnnotation(Component.class);

                    String beanName = declaredAnnotation.value();

                    BeanDefinition beanDefinition = new BeanDefinition();
                    beanDefinition.setClazz(clazz);
                    beanDifinitionMap.put(beanName, beanDefinition);


                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }

                if (clazz != null && clazz.isAnnotationPresent(Component.class)) {
                    System.out.println(absolutePath);
                }
            }
        }

    }
}
复制代码

 

三.Scope注解实现可配置的单例,多例对象

1.添加Scope注解,默认为singleton

2.被Compoent注解扫描的类被scope注解定义为Prototype视为多例,否则为单例

3.Bean加载到容器中

4.单例时从bean容器中取出,多例时创建新对象

复制代码
package annotiton;

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Scope {

    String value() default "singleton";
}
复制代码

 

 

 

 

 

 

复制代码
package spring;

import annotiton.BeanDefinition;
import annotiton.Component;
import annotiton.ComponentScan;
import annotiton.Scope;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.concurrent.ConcurrentHashMap;

public class CharkeyApplicationContext {

    private Class appConfig;

    private static ConcurrentHashMap<String, BeanDefinition> beanDifinitionMap = new ConcurrentHashMap<>();

    public CharkeyApplicationContext(Class configClass) {
        this.appConfig = appConfig;

        //扫描bean
        scan(configClass);
    }

    public Object getBean(String name) {
        BeanDefinition beanDefinition = beanDifinitionMap.get(name);
        String scope = beanDefinition.getScope();
        if(scope.equals("prototype"))return createBean(name, beanDefinition);
        return beanDefinition;
    }

    public Object createBean(String beanName, BeanDefinition beanDefinition) {
        Object object = null;
        try {
            Class clazz = beanDefinition.getClazz();
            object = clazz.getDeclaredConstructor().newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return object;
    }

    public void scan(Class app) {

        boolean annotationPresent = app.isAnnotationPresent(ComponentScan.class);
        if (!annotationPresent) throw new RuntimeException("没有配置类");

        ComponentScan componentScan = (ComponentScan) app.getDeclaredAnnotation(ComponentScan.class);
        String path = componentScan.value();
        System.out.println(path);

        ClassLoader classLoader = CharkeyApplicationContext.class.getClassLoader();
        path = path.replace(".", "/");
        System.out.println(path);
        URL resource = classLoader.getResource("service/impl");//"com/charkey/service"
        File file = new File(resource.getFile());
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (int i = 0; i < files.length; i++) {
                File file1 = files[i];
                String absolutePath = file1.getAbsolutePath();
                System.out.println(absolutePath);
                absolutePath = absolutePath.substring(absolutePath.indexOf("service"), absolutePath.indexOf(".class"));
                System.out.println(absolutePath);
                absolutePath = absolutePath.replace("\\", ".");
                System.out.println(absolutePath);

                Class<?> clazz = null;
                try {
                    clazz = classLoader.loadClass(absolutePath);

                    boolean isComponent = clazz.isAnnotationPresent(Component.class);
                    if (!isComponent) continue;
                    Component declaredAnnotation = clazz.getDeclaredAnnotation(Component.class);
                    String beanName = declaredAnnotation.value();

                    String scopeVal = "singleton";//默认单例Bean
                    boolean isScope = clazz.isAnnotationPresent(Scope.class);
                    if(isScope){
                        Scope scope1 = clazz.getDeclaredAnnotation(Scope.class);
                        scopeVal = scope1.value();
                    }

                    BeanDefinition beanDefinition = new BeanDefinition();
                    beanDefinition.setClazz(clazz);
                    beanDefinition.setScope(scopeVal);
                    beanDifinitionMap.put(beanName, beanDefinition);

                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }

                if (clazz != null && clazz.isAnnotationPresent(Component.class)) {
                    System.out.println(absolutePath);
                }
            }
        }

    }
}
复制代码

 

四.使用Autowired控制反转以及依赖注入

1.添加Autowired注解,增加requied属性

2.模拟DI创建bean容器

3.在创建bean时,把bean中的被autowired定义的属性加载

复制代码
package annotiton;

import java.lang.annotation.*;

@Target({ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {

    boolean value() default true;
}
复制代码

 

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package spring;
 
import annotiton.*;
 
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.concurrent.ConcurrentHashMap;
 
public class CharkeyApplicationContext {
 
    private Class appConfig;
 
    private static ConcurrentHashMap<String, BeanDefinition> beanDifinitionMap = new ConcurrentHashMap<>();
 
    private static ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();
 
    public CharkeyApplicationContext(Class configClass) {
        this.appConfig = appConfig;
 
        //扫描bean
        scan(configClass);
 
        beanDifinitionMap.forEach((beanName, clazz) -> {
            String scope = clazz.getScope();
            if (scope.equals("singleton")) {
                Object bean = createBean(beanName, clazz);
                singletonObjects.put(beanName, bean);
            }
        });
    }
 
    public Object getBean(String name) {
        BeanDefinition beanDefinition = beanDifinitionMap.get(name);
        String scope = beanDefinition.getScope();
        if(scope.equals("prototype"))return createBean(name, beanDefinition);
        return singletonObjects.get(name);
    }
 
    public Object createBean(String beanName, BeanDefinition beanDefinition) {
        Class clazz = beanDefinition.getClazz();
 
        try {
            Object o = clazz.getDeclaredConstructor().newInstance();
 
            Field[] declaredFields = clazz.getDeclaredFields();
            for (Field field : declaredFields) {
                boolean annotationPresent = field.isAnnotationPresent(Autowired.class);
                if (annotationPresent) {
                    Autowired autowired = (Autowired) clazz.getDeclaredAnnotation(Autowired.class);
                    boolean requied = autowired.value();
                    if(requied && o == null)throw new RuntimeException("没有找到bean");
                    Object bean = getBean(field.getName());
                    field.setAccessible(true);
                    field.set(o, bean);
                }
            }
            return o;
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
 
        return null;
    }
 
    public void scan(Class app) {
 
        boolean annotationPresent = app.isAnnotationPresent(ComponentScan.class);
        if (!annotationPresent) throw new RuntimeException("没有配置类");
 
        ComponentScan componentScan = (ComponentScan) app.getDeclaredAnnotation(ComponentScan.class);
        String path = componentScan.value();
        System.out.println(path);
 
        ClassLoader classLoader = CharkeyApplicationContext.class.getClassLoader();
        path = path.replace(".", "/");
        System.out.println(path);
        URL resource = classLoader.getResource("service/impl");//"com/charkey/service"
        File file = new File(resource.getFile());
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (int i = 0; i < files.length; i++) {
                File file1 = files[i];
                String absolutePath = file1.getAbsolutePath();
                System.out.println(absolutePath);
                absolutePath = absolutePath.substring(absolutePath.indexOf("service"), absolutePath.indexOf(".class"));
                System.out.println(absolutePath);
                absolutePath = absolutePath.replace("\\", ".");
                System.out.println(absolutePath);
 
                Class<?> clazz = null;
                try {
                    clazz = classLoader.loadClass(absolutePath);
 
                    boolean isComponent = clazz.isAnnotationPresent(Component.class);
                    if (!isComponent) continue;
                    Component declaredAnnotation = clazz.getDeclaredAnnotation(Component.class);
                    String beanName = declaredAnnotation.value();
 
                    String scopeVal = "singleton";//默认单例Bean
                    boolean isScope = clazz.isAnnotationPresent(Scope.class);
                    if(isScope){
                        Scope scope1 = clazz.getDeclaredAnnotation(Scope.class);
                        scopeVal = scope1.value();
                    }
 
                    BeanDefinition beanDefinition = new BeanDefinition();
                    beanDefinition.setClazz(clazz);
                    beanDefinition.setScope(scopeVal);
                    beanDifinitionMap.put(beanName, beanDefinition);
 
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
 
                if (clazz != null && clazz.isAnnotationPresent(Component.class)) {
                    System.out.println(absolutePath);
                }
            }
        }
 
    }
}

 五. Bean的生命周期

1.创建InitializingBean接口,定义初始化方法

2.修饰到需要初始化的Compent类上

3.创建Bean时,触发初始化方法

package annotiton;

public interface InitializingBean {

    void afterPropertiesSet() throws Exception;
}

 

 

复制代码
package service.impl;

import annotiton.Autowired;
import annotiton.Component;
import annotiton.InitializingBean;
import annotiton.Scope;
import service.OrderService;
import service.UserService;

@Component("userService")
@Scope("prototype")
public class UserServiceImpl implements UserService, InitializingBean {

    @Autowired
    private OrderService orderService;

    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void testAutowired(){
        System.out.println(orderService);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("bean初始化。。。");
        //System.out.println(getName());
    }
}
复制代码

 六. 监听Bean的初始化前、初始化、初始化后

1.Bean生命周期接口及实现 BeanPostProcessor 和 MyBeanPostInitialization,并在MyBeanPostInitialization添加Compent

2.扫描时将BeanPostProcessor 放到容器中

3.创建Bean时,从容器中取出BeanPostProcessor ,并执行初始化方法

package annotiton;

public interface BeanPostProcessor {

    Object postProcessorBeforeInintion(String beanName, Object bean);

    Object postProcessorAfterInintion(String beanName, Object bean);
}
复制代码
package service.impl;

import annotiton.BeanPostProcessor;
import annotiton.Component;
import service.OrderService;

@Component
public class MyBeanPostInitialization implements BeanPostProcessor {
    @Override
    public Object postProcessorBeforeInintion(String beanName, Object bean) {
        if (beanName.equals("orderService")) {
            OrderService orderService = (OrderService) bean;
            System.out.println("Bean开始初始化。。。");
            orderService.setName("charkey");
        }
        return bean;
    }

    @Override
    public Object postProcessorAfterInintion(String beanName, Object bean) {
        if (beanName.equals("orderService")) {
            OrderService orderService = (OrderService) bean;
            System.out.println("Bean初始化结束。。。name为。。。" + orderService.getName());
        }
        return bean;
    }
}
复制代码

 

 扫描

 

 

 

 

复制代码
package spring;

import annotiton.*;

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.concurrent.ConcurrentHashMap;

public class CharkeyApplicationContext {

    private Class appConfig;

    private static ConcurrentHashMap<String, BeanDefinition> beanDifinitionMap = new ConcurrentHashMap<>();

    private static ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();

    private static List<BeanPostProcessor> listBean = new ArrayList<>();

    public CharkeyApplicationContext(Class configClass) {
        this.appConfig = appConfig;

        //扫描bean
        scan(configClass);

        beanDifinitionMap.forEach((beanName, clazz) -> {
            String scope = clazz.getScope();
            if (scope.equals("singleton")) {
                Object bean = createBean(beanName, clazz);
                singletonObjects.put(beanName, bean);
            }
        });
    }

    public Object getBean(String name) {
        BeanDefinition beanDefinition = beanDifinitionMap.get(name);
        String scope = beanDefinition.getScope();
        if (scope.equals("prototype")) return createBean(name, beanDefinition);
        return singletonObjects.get(name);
    }

    public Object createBean(String beanName, BeanDefinition beanDefinition) {
        Class clazz = beanDefinition.getClazz();

        try {
            Object o = clazz.getDeclaredConstructor().newInstance();

            Field[] declaredFields = clazz.getDeclaredFields();
            for (Field field : declaredFields) {
                boolean annotationPresent = field.isAnnotationPresent(Autowired.class);
                if (annotationPresent) {
                    Autowired autowired = (Autowired) clazz.getDeclaredAnnotation(Autowired.class);
                    if (autowired == null) continue;
                    boolean requied = autowired.value();
                    if (requied && o == null) throw new RuntimeException("没有找到bean");
                    Object bean = getBean(field.getName());
                    field.setAccessible(true);
                    field.set(o, bean);
                }
            }
            //初始化前执行
            for (BeanPostProcessor processor : listBean) {
                processor.postProcessorBeforeInintion(beanName,o);
            }

            //初始化执行
            if (o instanceof InitializingBean) {
                ((InitializingBean) o).afterPropertiesSet();
            }

            //初始化前执行
            for (BeanPostProcessor processor : listBean) {
                processor.postProcessorAfterInintion(beanName,o);
            }
            return o;
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    public void scan(Class app) {

        boolean annotationPresent = app.isAnnotationPresent(ComponentScan.class);
        if (!annotationPresent) throw new RuntimeException("没有配置类");

        ComponentScan componentScan = (ComponentScan) app.getDeclaredAnnotation(ComponentScan.class);
        String path = componentScan.value();
        System.out.println(path);

        ClassLoader classLoader = CharkeyApplicationContext.class.getClassLoader();
        path = path.replace(".", "/");
        System.out.println(path);
        URL resource = classLoader.getResource("service/impl");//"com/charkey/service"
        File file = new File(resource.getFile());
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (int i = 0; i < files.length; i++) {
                File file1 = files[i];
                String absolutePath = file1.getAbsolutePath();
                System.out.println(absolutePath);
                absolutePath = absolutePath.substring(absolutePath.indexOf("service"), absolutePath.indexOf(".class"));
                System.out.println(absolutePath);
                absolutePath = absolutePath.replace("\\", ".");
                System.out.println(absolutePath);

                Class<?> clazz = null;
                try {
                    clazz = classLoader.loadClass(absolutePath);

                    boolean isComponent = clazz.isAnnotationPresent(Component.class);
                    if (!isComponent) continue;
                    Component declaredAnnotation = clazz.getDeclaredAnnotation(Component.class);
                    String beanName = declaredAnnotation.value();

                    if (BeanPostProcessor.class.isAssignableFrom(clazz)) {//MyBeanPostInitialization
                        BeanPostProcessor beanPostProcessor = (BeanPostProcessor) clazz.getDeclaredConstructor().newInstance();
                        listBean.add(beanPostProcessor);
                    }

                    if((clazz.getName()).indexOf("MyBeanPostInitialization") > 0)continue;
                    if((beanName == null || beanName.equals("")) ){

                        beanName = clazz.getName().substring(clazz.getName().lastIndexOf(".")+1);

                        beanName = Character.toLowerCase(beanName.charAt(0)) +
                                (beanName.length() > 1 ? beanName.substring(1) :"");

                        beanName = beanName.replace("Impl","");
                    }

                    String scopeVal = "singleton";//默认单例Bean
                    boolean isScope = clazz.isAnnotationPresent(Scope.class);
                    if (isScope) {
                        Scope scope1 = clazz.getDeclaredAnnotation(Scope.class);
                        scopeVal = scope1.value();
                    }

                    BeanDefinition beanDefinition = new BeanDefinition();
                    beanDefinition.setClazz(clazz);
                    beanDefinition.setScope(scopeVal);
                    beanDifinitionMap.put(beanName, beanDefinition);

                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                }

                if (clazz != null && clazz.isAnnotationPresent(Component.class)) {
                    System.out.println(absolutePath);
                }
            }
        }

    }
}
复制代码

 五.实现AOP

在Bean初始化完成后,配置JDK的Proxy对象并返回

复制代码
package service.impl;

import annotiton.BeanPostProcessor;
import annotiton.Component;
import service.OrderService;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

@Component
public class MyBeanPostInitialization implements BeanPostProcessor {
    @Override
    public Object postProcessorBeforeInintion(String beanName, Object bean) {
        if (beanName.equals("orderService")) {
            OrderService orderService = (OrderService) bean;
            System.out.println("Bean开始初始化。。。");
            orderService.setName("charkey");
        }
        return bean;
    }

    @Override
    public Object postProcessorAfterInintion(String beanName, Object bean) {
        if (beanName.equals("orderService")) {
            OrderService orderService = (OrderService) bean;
            System.out.println("Bean初始化结束。。。name为。。。" + orderService.getName());

            Object proxyInstance = Proxy.newProxyInstance(MyBeanPostInitialization.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println("执行test方法前AOP执行逻辑。。。。。");
                    return method.invoke(bean, args);
                }
            });

            return proxyInstance;
        }
        return bean;
    }
}
复制代码

 

 

 

posted @   蔡徐坤1987  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示