├── .gitignore
├── .idea
├── misc.xml
└── modules.xml
├── MyOwnSpring.iml
└── src
├── com
└── kciray
│ ├── CustomPostProcessor.java
│ ├── Main.java
│ ├── ProductService.java
│ └── PromotionsService.java
├── javax
└── annotation
│ └── PreDestroy.java
└── org
└── springframework
├── beans
└── factory
│ ├── BeanFactory.java
│ ├── BeanNameAware.java
│ ├── DisposableBean.java
│ ├── InitializingBean.java
│ ├── annotation
│ └── Autowired.java
│ ├── config
│ └── BeanPostProcessor.java
│ └── stereotype
│ ├── Component.java
│ └── Service.java
└── context
├── ApplicationContext.java
├── ApplicationListener.java
└── event
└── ContextClosedEvent.java
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 |
4 | # Log file
5 | *.log
6 |
7 | # BlueJ files
8 | *.ctxt
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | *.jar
15 | *.war
16 | *.nar
17 | *.ear
18 | *.zip
19 | *.tar.gz
20 | *.rar
21 |
22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
23 | hs_err_pid*
24 |
25 | # User-specific stuff
26 | .idea/**/workspace.xml
27 | .idea/**/tasks.xml
28 | .idea/**/usage.statistics.xml
29 | .idea/**/dictionaries
30 | .idea/**/shelf
31 | .idea/sonarlint
32 |
33 | # Generated files
34 | .idea/**/contentModel.xml
35 |
36 | # IntelliJ
37 | out/
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/MyOwnSpring.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/com/kciray/CustomPostProcessor.java:
--------------------------------------------------------------------------------
1 | package com.kciray;
2 |
3 | import org.springframework.beans.factory.config.BeanPostProcessor;
4 |
5 | public class CustomPostProcessor implements BeanPostProcessor {
6 | @Override
7 | public Object postProcessBeforeInitialization(Object bean, String beanName) {
8 | System.out.println("---CustomPostProcessor Before " + beanName);
9 | return bean;
10 | }
11 |
12 | @Override
13 | public Object postProcessAfterInitialization(Object bean, String beanName) {
14 | System.out.println("---CustomPostProcessor After " + beanName);
15 | return bean;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/com/kciray/Main.java:
--------------------------------------------------------------------------------
1 | package com.kciray;
2 |
3 | import org.springframework.beans.factory.BeanFactory;
4 | import org.springframework.context.ApplicationContext;
5 |
6 | public class Main {
7 |
8 | public static void main(String[] args){
9 | new Main();
10 | }
11 |
12 | public Main(){
13 | try {
14 | testBeanFactory();
15 | testContext();
16 | }catch (ReflectiveOperationException e){
17 | e.printStackTrace();
18 | }
19 | }
20 |
21 | void testBeanFactory() throws ReflectiveOperationException{
22 | BeanFactory beanFactory = new BeanFactory();
23 | beanFactory.addPostProcessor(new CustomPostProcessor());
24 |
25 | beanFactory.instantiate("com.kciray");
26 | beanFactory.populateProperties();
27 | beanFactory.injectBeanNames();
28 | beanFactory.initializeBeans();
29 |
30 | ProductService productService = (ProductService) beanFactory.getBean("productService");
31 | System.out.println(productService);//ProductService@612
32 |
33 | PromotionsService promotionsService = productService.getPromotionsService();
34 | System.out.println(promotionsService);
35 | System.out.println("Bean name = " + promotionsService.getBeanName());
36 |
37 | System.out.println(promotionsService.getClass());
38 |
39 | beanFactory.close();
40 | }
41 |
42 | void testContext() throws ReflectiveOperationException{
43 | ApplicationContext applicationContext = new ApplicationContext("com.kciray");
44 | applicationContext.close();
45 | }
46 | }
--------------------------------------------------------------------------------
/src/com/kciray/ProductService.java:
--------------------------------------------------------------------------------
1 | package com.kciray;
2 |
3 | import org.springframework.beans.factory.DisposableBean;
4 | import org.springframework.beans.factory.InitializingBean;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.beans.factory.stereotype.Component;
7 |
8 | import javax.annotation.PreDestroy;
9 |
10 | @Component
11 | public class ProductService implements InitializingBean, DisposableBean {
12 | @Autowired
13 | private PromotionsService promotionsService;
14 |
15 | public PromotionsService getPromotionsService() {
16 | return promotionsService;
17 | }
18 |
19 | public void setPromotionsService(PromotionsService promotionsService) {
20 | this.promotionsService = promotionsService;
21 | }
22 |
23 | @Override
24 | public void afterPropertiesSet() {
25 | System.out.println("PromotionsService init...");
26 | }
27 |
28 | @Override
29 | public void destroy() {
30 | System.out.println("PromotionsService destroy...");
31 | }
32 |
33 | @PreDestroy
34 | public void destroy2() {
35 | System.out.println("PromotionsService @PreDestroy...");
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/com/kciray/PromotionsService.java:
--------------------------------------------------------------------------------
1 | package com.kciray;
2 |
3 | import org.springframework.beans.factory.BeanNameAware;
4 | import org.springframework.beans.factory.stereotype.Component;
5 | import org.springframework.beans.factory.stereotype.Service;
6 | import org.springframework.context.ApplicationListener;
7 | import org.springframework.context.event.ContextClosedEvent;
8 |
9 | @Service
10 | public class PromotionsService implements BeanNameAware, ApplicationListener {
11 | private String beanName;
12 |
13 | @Override
14 | public void setBeanName(String name) {
15 | beanName = name;
16 | }
17 |
18 | public String getBeanName() {
19 | return beanName;
20 | }
21 |
22 | @Override
23 | public void onApplicationEvent(ContextClosedEvent event) {
24 | System.out.println(">> ContextClosed EVENT");
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/javax/annotation/PreDestroy.java:
--------------------------------------------------------------------------------
1 | package javax.annotation;
2 |
3 | import java.lang.annotation.Retention;
4 | import java.lang.annotation.RetentionPolicy;
5 |
6 | @Retention(RetentionPolicy.RUNTIME)
7 | public @interface PreDestroy {
8 | }
--------------------------------------------------------------------------------
/src/org/springframework/beans/factory/BeanFactory.java:
--------------------------------------------------------------------------------
1 | package org.springframework.beans.factory;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.beans.factory.config.BeanPostProcessor;
5 | import org.springframework.beans.factory.stereotype.Component;
6 | import org.springframework.beans.factory.stereotype.Service;
7 |
8 | import javax.annotation.PreDestroy;
9 | import java.io.File;
10 | import java.io.IOException;
11 | import java.lang.reflect.Field;
12 | import java.lang.reflect.InvocationTargetException;
13 | import java.lang.reflect.Method;
14 | import java.net.URISyntaxException;
15 | import java.net.URL;
16 | import java.net.URLClassLoader;
17 | import java.util.ArrayList;
18 | import java.util.Collections;
19 | import java.util.Enumeration;
20 | import java.util.HashMap;
21 | import java.util.List;
22 | import java.util.Map;
23 |
24 | public class BeanFactory {
25 | private Map singletons = new HashMap();
26 |
27 | public Object getBean(String beanName) {
28 | return singletons.get(beanName);
29 | }
30 |
31 | private List postProcessors = new ArrayList<>();
32 |
33 | public void addPostProcessor(BeanPostProcessor postProcessor) {
34 | postProcessors.add(postProcessor);
35 | }
36 |
37 | public Map getSingletons() {
38 | return singletons;
39 | }
40 |
41 | public void instantiate(String basePackage) {
42 | try {
43 | ClassLoader classLoader = ClassLoader.getSystemClassLoader();
44 |
45 | String path = basePackage.replace('.', '/');
46 | Enumeration resources = classLoader.getResources(path);
47 |
48 | while (resources.hasMoreElements()) {
49 | URL resource = resources.nextElement();
50 | File file = new File(resource.toURI());
51 |
52 | for (File classFile : file.listFiles()) {
53 | String fileName = classFile.getName();//ProductService.class
54 | System.out.println(fileName);
55 | if (fileName.endsWith(".class")) {
56 | String className = fileName.substring(0, fileName.lastIndexOf("."));
57 |
58 | Class classObject = Class.forName(basePackage + "." + className);
59 |
60 | if (classObject.isAnnotationPresent(Component.class) || classObject.isAnnotationPresent(Service.class)) {
61 | System.out.println("Component: " + classObject);
62 |
63 | Object instance = classObject.newInstance();//=new CustomClass()
64 | String beanName = className.substring(0, 1).toLowerCase() + className.substring(1);
65 | singletons.put(beanName, instance);
66 | }
67 | }
68 | }
69 | }
70 | } catch (IOException | URISyntaxException | ClassNotFoundException | IllegalAccessException | InstantiationException e) {
71 | e.printStackTrace();
72 | }
73 | }
74 |
75 | public void populateProperties() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
76 | System.out.println("==populateProperties==");
77 |
78 | for (Object object : singletons.values()) {
79 | for (Field field : object.getClass().getDeclaredFields()) {
80 | if (field.isAnnotationPresent(Autowired.class)) {
81 |
82 | for (Object dependency : singletons.values()) {
83 | if (dependency.getClass().equals(field.getType())) {
84 | String setterName = "set" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
85 | System.out.println("Setter name = " + setterName);
86 | Method setter = object.getClass().getMethod(setterName, dependency.getClass());
87 | setter.invoke(object, dependency);
88 | }
89 | }
90 | }
91 | }
92 | }
93 | }
94 |
95 | public void injectBeanNames() {
96 | for (String name : singletons.keySet()) {
97 | Object bean = singletons.get(name);
98 |
99 | if (bean instanceof BeanNameAware) {
100 | ((BeanNameAware) bean).setBeanName(name);
101 | }
102 | }
103 | }
104 |
105 | public void initializeBeans() {
106 | for (String name : singletons.keySet()) {
107 | Object bean = singletons.get(name);
108 |
109 | for (BeanPostProcessor postProcessor : postProcessors) {
110 | postProcessor.postProcessBeforeInitialization(bean, name);
111 | }
112 |
113 | if (bean instanceof InitializingBean) {
114 | ((InitializingBean) bean).afterPropertiesSet();
115 | }
116 |
117 | for (BeanPostProcessor postProcessor : postProcessors) {
118 | postProcessor.postProcessAfterInitialization(bean, name);
119 | }
120 | }
121 | }
122 |
123 | public void close() {
124 | for (Object bean : singletons.values()) {
125 | for (Method method : bean.getClass().getMethods()) {
126 | if (method.isAnnotationPresent(PreDestroy.class)) {
127 | try {
128 | method.invoke(bean);
129 | } catch (IllegalAccessException e) {
130 | e.printStackTrace();
131 | } catch (InvocationTargetException e) {
132 | e.printStackTrace();
133 | }
134 | }
135 | }
136 |
137 | if (bean instanceof DisposableBean) {
138 | ((DisposableBean) bean).destroy();
139 | }
140 | }
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/src/org/springframework/beans/factory/BeanNameAware.java:
--------------------------------------------------------------------------------
1 | package org.springframework.beans.factory;
2 |
3 | public interface BeanNameAware {
4 | void setBeanName(String name);
5 | }
--------------------------------------------------------------------------------
/src/org/springframework/beans/factory/DisposableBean.java:
--------------------------------------------------------------------------------
1 | package org.springframework.beans.factory;
2 |
3 | public interface DisposableBean {
4 | void destroy();
5 | }
--------------------------------------------------------------------------------
/src/org/springframework/beans/factory/InitializingBean.java:
--------------------------------------------------------------------------------
1 | package org.springframework.beans.factory;
2 |
3 | public interface InitializingBean {
4 | void afterPropertiesSet();
5 | }
6 |
--------------------------------------------------------------------------------
/src/org/springframework/beans/factory/annotation/Autowired.java:
--------------------------------------------------------------------------------
1 | package org.springframework.beans.factory.annotation;
2 |
3 | import java.lang.annotation.Retention;
4 | import java.lang.annotation.RetentionPolicy;
5 |
6 | @Retention(RetentionPolicy.RUNTIME)
7 | public @interface Autowired {
8 | }
9 |
--------------------------------------------------------------------------------
/src/org/springframework/beans/factory/config/BeanPostProcessor.java:
--------------------------------------------------------------------------------
1 | package org.springframework.beans.factory.config;
2 |
3 | public interface BeanPostProcessor {
4 | Object postProcessBeforeInitialization(Object bean, String beanName);
5 | Object postProcessAfterInitialization(Object bean, String beanName);
6 | }
--------------------------------------------------------------------------------
/src/org/springframework/beans/factory/stereotype/Component.java:
--------------------------------------------------------------------------------
1 | package org.springframework.beans.factory.stereotype;
2 |
3 | import java.lang.annotation.Retention;
4 | import java.lang.annotation.RetentionPolicy;
5 |
6 | @Retention(RetentionPolicy.RUNTIME)
7 | public @interface Component {
8 | }
9 |
--------------------------------------------------------------------------------
/src/org/springframework/beans/factory/stereotype/Service.java:
--------------------------------------------------------------------------------
1 | package org.springframework.beans.factory.stereotype;
2 |
3 | import java.lang.annotation.Retention;
4 | import java.lang.annotation.RetentionPolicy;
5 |
6 | @Retention(RetentionPolicy.RUNTIME)
7 | public @interface Service {
8 | }
--------------------------------------------------------------------------------
/src/org/springframework/context/ApplicationContext.java:
--------------------------------------------------------------------------------
1 | package org.springframework.context;
2 |
3 | import org.springframework.beans.factory.BeanFactory;
4 | import org.springframework.context.event.ContextClosedEvent;
5 |
6 | import java.lang.reflect.InvocationTargetException;
7 | import java.lang.reflect.Method;
8 | import java.lang.reflect.ParameterizedType;
9 | import java.lang.reflect.Type;
10 |
11 | public class ApplicationContext {
12 | private BeanFactory beanFactory = new BeanFactory();
13 |
14 | public ApplicationContext(String basePackage) throws ReflectiveOperationException{
15 | System.out.println("******Context is under construction******");
16 |
17 | beanFactory.instantiate(basePackage);
18 | beanFactory.populateProperties();
19 | beanFactory.injectBeanNames();
20 | beanFactory.initializeBeans();
21 | }
22 |
23 | public void close() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
24 | beanFactory.close();
25 |
26 | for(Object bean : beanFactory.getSingletons().values()) {
27 | if (bean instanceof ApplicationListener) {
28 | for(Type type: bean.getClass().getGenericInterfaces()){
29 | if(type instanceof ParameterizedType){
30 | ParameterizedType parameterizedType = (ParameterizedType) type;
31 |
32 | Type firstParameter = parameterizedType.getActualTypeArguments()[0];
33 | if(firstParameter.equals(ContextClosedEvent.class)){
34 | Method method = bean.getClass().getMethod("onApplicationEvent", ContextClosedEvent.class);
35 | method.invoke(bean, new ContextClosedEvent());
36 | }
37 | }
38 | }
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/org/springframework/context/ApplicationListener.java:
--------------------------------------------------------------------------------
1 | package org.springframework.context;
2 |
3 | public interface ApplicationListener{
4 | void onApplicationEvent(E event);
5 | }
--------------------------------------------------------------------------------
/src/org/springframework/context/event/ContextClosedEvent.java:
--------------------------------------------------------------------------------
1 | package org.springframework.context.event;
2 |
3 | public class ContextClosedEvent {
4 | }
5 |
--------------------------------------------------------------------------------