├── .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 | --------------------------------------------------------------------------------