代碼結構
模擬spring源碼
BeanDefinition
public class BeanDefinition { private Class aClass; private String scope; private Boolean lazy; public Class getaClass() { return aClass; } public void setaClass(Class aClass) { this.aClass = aClass; } public String getScope() { return scope; } public void setScope(String scope) { this.scope = scope; } public Boolean getLazy() { return lazy; } public void setLazy(Boolean lazy) { this.lazy = lazy; } }
BeanNameAware
public interface BeanNameAware { void setBeanName(String beanName); }
BeanPostProcessor
public interface BeanPostProcessor { default Object postProcessBeforeInitialization(Object bean, String beanName) { return bean; } /** * 初始化後,創建bean的過程中,每一個bean都會調用此方法,也可以單獨判斷,可以用來實現aop */ default Object postProcessAfterInitialization(Object bean, String beanName) { return bean; } }
InitializingBean
public interface InitializingBean { void afterPropertiesSet(); }
MyApplicationContext
public class MyApplicationContext { private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>(); //單例池 private Map<String, Object> singletonObjects = new HashMap<>(); private List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>(); public MyApplicationContext(Class<MyAppConfig> myAppConfigClass) throws ClassNotFoundException, NoSuchMethodException { //掃描 構建Bean定義,放在beanDefinitionMap中 scan(myAppConfigClass); //掃描完,遍歷beanDefinitionMap,找出所有的單例bean,創建單例bean並放在單例池中 //單例模式先創建bean再放在單例池中 Set<Map.Entry<String, BeanDefinition>> entries = beanDefinitionMap.entrySet(); for (Map.Entry<String, BeanDefinition> entry : entries) { String beanName = entry.getKey(); BeanDefinition beanDefinition = entry.getValue(); String scope = beanDefinition.getScope(); if ("singleton".equals(scope)) { Object singletonBean = createBean(beanName, beanDefinition); singletonObjects.put(beanName, singletonBean); } } } private void scan(Class<?> myAppConfigClass) throws ClassNotFoundException { if (myAppConfigClass.isAnnotationPresent(MyComponentScan.class)) { MyComponentScan annotation = myAppConfigClass.getAnnotation(MyComponentScan.class); //掃描路徑 String path = annotation.value(); System.out.println("掃描路徑:" + path); path = path.replace(".", "/"); ClassLoader classLoader = MyApplicationContext.class.getClassLoader(); URL resource = classLoader.getResource(path); File fileDirectory = new File(resource.getFile()); if (fileDirectory.isDirectory()) { File[] files = fileDirectory.listFiles(); //遍歷class文件 for (File file : files) { String absolutePath = file.getAbsolutePath(); //System.out.println("absolutePath->" + absolutePath); //加載類 //轉換路徑格式 absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.lastIndexOf(".class")); absolutePath = absolutePath.replace("\\", "."); //System.out.println("absolutePath->" + absolutePath); //class文件加載爲class對象 //Class<?> aClass = Class.forName(absolutePath); Class<?> aClass = classLoader.loadClass(absolutePath); //找到有Component註解的類 if (aClass.isAnnotationPresent(MyComponent.class)) { System.out.println(absolutePath + "有component註解"); //如果一個類有component註解,再判斷是否實現了BeanPostProcessor接口 if (BeanPostProcessor.class.isAssignableFrom(aClass)) { try { BeanPostProcessor instance = (BeanPostProcessor) aClass.getConstructor().newInstance(); //保存BeanPostProcessor,等到創建bean的時候再使用 beanPostProcessorList.add(instance); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } //不用獲取BeanPostProcessor的BeanDefinition } else { MyComponent myComponent = aClass.getAnnotation(MyComponent.class); //註解中配置的beanName String beanName = myComponent.value(); //如果未指定beanName if ("".equals(beanName)) { //根據類型生成名字 beanName = Introspector.decapitalize(aClass.getSimpleName()); } //如果有類有Component這個註解,那麼需要創建一個BeanDefinition描述該bean BeanDefinition beanDefinition = new BeanDefinition(); beanDefinition.setaClass(aClass); //再判斷是單例還是原型 if (aClass.isAnnotationPresent(MyScope.class)) { MyScope myScope = aClass.getAnnotation(MyScope.class); String scope = myScope.value(); beanDefinition.setScope(scope); } else { //沒有註解,默認是單例,如果是單例 beanDefinition.setScope("singleton"); } beanDefinitionMap.put(beanName, beanDefinition); } } } } } } public Object getBean(String beanName) throws NoSuchMethodException { //如果沒有則說明沒有定義這個bean if (!beanDefinitionMap.containsKey(beanName)) { System.out.println("找不到該bean"); return null; } BeanDefinition beanDefinition = beanDefinitionMap.get(beanName); String scope = beanDefinition.getScope(); //如果是單例,直接從單例池中獲取 if ("singleton".equals(scope)) { Object singletonBean = singletonObjects.get(beanName); //可能因爲掃描順序問題,還沒有初始化成功 if (singletonBean == null) { singletonBean = createBean(beanName, beanDefinition); singletonObjects.put(beanName, singletonBean); } return singletonBean; } else { //原型模式每次都要重新創建 Object prototypeBean = createBean(beanName, beanDefinition); return prototypeBean; } } //創建bean public Object createBean(String beanName, BeanDefinition beanDefinition) throws NoSuchMethodException { Class aClass = beanDefinition.getaClass(); //調用構造方法創建對象 Object instance = null; try { instance = aClass.getConstructor().newInstance(); //創建bean的過程中進行依賴注入 //遍歷類的屬性 Field[] fields = aClass.getDeclaredFields(); for (Field field : fields) { //判斷屬性上是否有autowired註解 if (field.isAnnotationPresent(MyAutowired.class)) { field.setAccessible(true); //賦值 -> 先根據類型再根據名字去找,我們這裏只使用名字去找 會有循環依賴問題 field.set(instance, getBean(field.getName())); } } //依賴注入完成後,beanNameAware if (instance instanceof BeanNameAware) { ((BeanNameAware) instance).setBeanName(beanName); } //初始化前 for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) { instance = beanPostProcessor.postProcessBeforeInitialization(instance, beanName); } //依賴注入完成之後進行初始化操作 //判斷是否實現了InitializingBean接口 if (instance instanceof InitializingBean) { ((InitializingBean) instance).afterPropertiesSet(); } //初始化後 //new MyBeanPostProcessor().postProcessAfterInitialization(instance, beanName); for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) { instance = beanPostProcessor.postProcessAfterInitialization(instance, beanName); } } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } return instance; } }
MyAutowired
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface MyAutowired { String value() default ""; }
MyComponent
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface MyComponent { String value() default ""; }
MyComponentScan
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface MyComponentScan { String value() default ""; }
MyScope
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface MyScope { String value() default ""; }
測試代碼
MyAppConfig
@MyComponentScan("com.sy.test") public class MyAppConfig { }
MyBeanPostProcessor
@MyComponent public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessAfterInitialization(Object bean, String beanName) { //創建bean的過程中,每一個bean都會調用此方法,也可以單獨判斷 if ("orderService".equals(beanName)) { System.out.println("生成orderService的代理對象"); Object proxyInstance = Proxy.newProxyInstance(MyBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //切面邏輯 System.out.println(beanName + "執行切面邏輯"); return method.invoke(bean, args); } }); return proxyInstance; } else { System.out.println(beanName + "執行bean的後置處理器"); return bean; } } }
MyValue
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface MyValue { String value() default ""; }
MyValueBeanPostProcessor
@MyComponent public class MyValueBeanPostProcessor implements BeanPostProcessor { /** * 測試通過自定義註解給屬性賦值 */ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) { Field[] declaredFields = bean.getClass().getDeclaredFields(); for (Field field : declaredFields) { if (field.isAnnotationPresent(MyValue.class)) { field.setAccessible(true); MyValue annotation = field.getAnnotation(MyValue.class); String value = annotation.value(); try { field.set(bean,value); } catch (IllegalAccessException e) { e.printStackTrace(); } } } return bean; } }
OrderInterface
public interface OrderInterface { void test(); }
OrderService
@MyComponent @MyScope("prototype") public class OrderService implements OrderInterface, InitializingBean { @MyAutowired private UserService userService; @MyValue("xxxxxx") private String testStr; @Override public void test() { System.out.println("myOrderService.test.........."); System.out.println("myOrderService.myUserService->" + userService); System.out.println("myOrderService.testStr->" + testStr); } @Override public void afterPropertiesSet() { System.out.println("myOrderService.afterPropertiesSet..."); } }
UserService
@MyScope("singleton") @MyComponent("userService") public class UserService implements InitializingBean, BeanNameAware { private String beanName; public void test() { System.out.println("myUserService.test.............."); } @Override public void afterPropertiesSet() { System.out.println("myUserService.afterPropertiesSet..."); } @Override public void setBeanName(String beanName) { System.out.println("userService.setBeanName..."); this.beanName = beanName; } }
TestSpring
public class TestSpring { @Test public void testCreateBean() throws ClassNotFoundException, NoSuchMethodException { //首先掃描 -> 創建單例bean BeanDefinition BeanPostProcessor MyApplicationContext applicationContent = new MyApplicationContext(MyAppConfig.class); UserService userService = (UserService) applicationContent.getBean("userService"); userService.test(); System.out.println("userService->" + applicationContent.getBean("userService")); System.out.println("userService->" + applicationContent.getBean("userService")); OrderInterface orderService = (OrderInterface) applicationContent.getBean("orderService"); orderService.test(); System.out.println("orderService->" + applicationContent.getBean("orderService")); System.out.println("orderService->" + applicationContent.getBean("orderService")); } }