├── .gitignore ├── LICENSE ├── README.md ├── README_en.md ├── assets ├── application-context-life-cycle.drawio ├── application-context-life-cycle.png ├── auto-proxy.drawio ├── auto-proxy.png ├── aware-interface.drawio ├── aware-interface.png ├── bean-definition-and-bean-definition-registry.png ├── chainProceed.png ├── init-and-destroy-method.drawio ├── init-and-destroy-method.png ├── instantiation-strategy.png ├── populate-proxy-bean-with-property-values.drawio ├── populate-proxy-bean-with-property-values.png ├── prototype-bean.drawio ├── prototype-bean.png ├── resource.png ├── spring-framework.png └── xml-file-define-bean.png ├── changelog.md ├── pom.xml └── src ├── main └── java │ └── org │ └── springframework │ ├── aop │ ├── AdvisedSupport.java │ ├── Advisor.java │ ├── AfterAdvice.java │ ├── AfterReturningAdvice.java │ ├── BeforeAdvice.java │ ├── ClassFilter.java │ ├── MethodBeforeAdvice.java │ ├── MethodMatcher.java │ ├── Pointcut.java │ ├── PointcutAdvisor.java │ ├── TargetSource.java │ ├── aspectj │ │ ├── AspectJExpressionPointcut.java │ │ └── AspectJExpressionPointcutAdvisor.java │ └── framework │ │ ├── AdvisorChainFactory.java │ │ ├── AopProxy.java │ │ ├── CglibAopProxy.java │ │ ├── DefaultAdvisorChainFactory.java │ │ ├── JdkDynamicAopProxy.java │ │ ├── ProxyFactory.java │ │ ├── ReflectiveMethodInvocation.java │ │ ├── adapter │ │ ├── AfterReturningAdviceInterceptor.java │ │ └── MethodBeforeAdviceInterceptor.java │ │ └── autoproxy │ │ └── DefaultAdvisorAutoProxyCreator.java │ ├── beans │ ├── BeansException.java │ ├── PropertyValue.java │ ├── PropertyValues.java │ └── factory │ │ ├── Aware.java │ │ ├── BeanFactory.java │ │ ├── BeanFactoryAware.java │ │ ├── ConfigurableListableBeanFactory.java │ │ ├── DisposableBean.java │ │ ├── FactoryBean.java │ │ ├── HierarchicalBeanFactory.java │ │ ├── InitializingBean.java │ │ ├── ListableBeanFactory.java │ │ ├── ObjectFactory.java │ │ ├── PropertyPlaceholderConfigurer.java │ │ ├── annotation │ │ ├── Autowired.java │ │ ├── AutowiredAnnotationBeanPostProcessor.java │ │ ├── Qualifier.java │ │ └── Value.java │ │ ├── config │ │ ├── AutowireCapableBeanFactory.java │ │ ├── BeanDefinition.java │ │ ├── BeanFactoryPostProcessor.java │ │ ├── BeanPostProcessor.java │ │ ├── BeanReference.java │ │ ├── ConfigurableBeanFactory.java │ │ ├── InstantiationAwareBeanPostProcessor.java │ │ └── SingletonBeanRegistry.java │ │ ├── support │ │ ├── AbstractAutowireCapableBeanFactory.java │ │ ├── AbstractBeanDefinitionReader.java │ │ ├── AbstractBeanFactory.java │ │ ├── BeanDefinitionReader.java │ │ ├── BeanDefinitionRegistry.java │ │ ├── CglibSubclassingInstantiationStrategy.java │ │ ├── DefaultListableBeanFactory.java │ │ ├── DefaultSingletonBeanRegistry.java │ │ ├── DisposableBeanAdapter.java │ │ ├── InstantiationStrategy.java │ │ └── SimpleInstantiationStrategy.java │ │ └── xml │ │ └── XmlBeanDefinitionReader.java │ ├── context │ ├── ApplicationContext.java │ ├── ApplicationContextAware.java │ ├── ApplicationEvent.java │ ├── ApplicationEventPublisher.java │ ├── ApplicationListener.java │ ├── ConfigurableApplicationContext.java │ ├── annotation │ │ ├── ClassPathBeanDefinitionScanner.java │ │ ├── ClassPathScanningCandidateComponentProvider.java │ │ └── Scope.java │ ├── event │ │ ├── AbstractApplicationEventMulticaster.java │ │ ├── ApplicationContextEvent.java │ │ ├── ApplicationEventMulticaster.java │ │ ├── ContextClosedEvent.java │ │ ├── ContextRefreshedEvent.java │ │ └── SimpleApplicationEventMulticaster.java │ └── support │ │ ├── AbstractApplicationContext.java │ │ ├── AbstractRefreshableApplicationContext.java │ │ ├── AbstractXmlApplicationContext.java │ │ ├── ApplicationContextAwareProcessor.java │ │ ├── ClassPathXmlApplicationContext.java │ │ └── ConversionServiceFactoryBean.java │ ├── core │ ├── convert │ │ ├── ConversionService.java │ │ ├── converter │ │ │ ├── Converter.java │ │ │ ├── ConverterFactory.java │ │ │ ├── ConverterRegistry.java │ │ │ └── GenericConverter.java │ │ └── support │ │ │ ├── DefaultConversionService.java │ │ │ ├── GenericConversionService.java │ │ │ └── StringToNumberConverterFactory.java │ └── io │ │ ├── ClassPathResource.java │ │ ├── DefaultResourceLoader.java │ │ ├── FileSystemResource.java │ │ ├── Resource.java │ │ ├── ResourceLoader.java │ │ └── UrlResource.java │ ├── stereotype │ └── Component.java │ └── util │ └── StringValueResolver.java └── test ├── java └── org │ └── springframework │ └── test │ ├── aop │ ├── AutoProxyTest.java │ ├── DynamicProxyTest.java │ ├── PointcutExpressionTest.java │ └── ProxyFactoryTest.java │ ├── bean │ ├── A.java │ ├── B.java │ ├── Car.java │ └── Person.java │ ├── common │ ├── ABeforeAdvice.java │ ├── CarFactoryBean.java │ ├── ConvertersFactoryBean.java │ ├── CustomBeanFactoryPostProcessor.java │ ├── CustomerBeanPostProcessor.java │ ├── StringToBooleanConverter.java │ ├── StringToIntegerConverter.java │ ├── StringToLocalDateConverter.java │ ├── WorldServiceAfterReturnAdvice.java │ ├── WorldServiceBeforeAdvice.java │ ├── WorldServiceInterceptor.java │ └── event │ │ ├── ContextClosedEventListener.java │ │ ├── ContextRefreshedEventListener.java │ │ ├── CustomEvent.java │ │ └── CustomEventListener.java │ ├── expanding │ └── PropertyPlaceholderConfigurerTest.java │ ├── ioc │ ├── ApplicationContextTest.java │ ├── AutowiredAnnotationTest.java │ ├── AwareInterfaceTest.java │ ├── BeanDefinitionAndBeanDefinitionRegistryTest.java │ ├── BeanFactoryPostProcessorAndBeanPostProcessorTest.java │ ├── CircularReferenceWithProxyBeanTest.java │ ├── CircularReferenceWithoutProxyBeanTest.java │ ├── EventAndEventListenerTest.java │ ├── FactoryBeanTest.java │ ├── HelloService.java │ ├── InitAndDestoryMethodTest.java │ ├── LazyInitTest.java │ ├── PackageScanTest.java │ ├── PopulateBeanWithPropertyValuesTest.java │ ├── PrototypeBeanTest.java │ ├── ResourceAndResourceLoaderTest.java │ ├── TypeConversionFirstPartTest.java │ ├── TypeConversionSecondPartTest.java │ ├── ValueAnnotationTest.java │ └── XmlFileDefineBeanTest.java │ └── service │ ├── HelloService.java │ ├── WorldService.java │ └── WorldServiceImpl.java └── resources ├── auto-proxy.xml ├── autowired-annotation.xml ├── car.properties ├── circular-reference-with-proxy-bean.xml ├── circular-reference-without-proxy-bean.xml ├── event-and-event-listener.xml ├── factory-bean.xml ├── hello.txt ├── init-and-destroy-method.xml ├── lazy-test.xml ├── package-scan.xml ├── populate-proxy-bean-with-property-values.xml ├── property-placeholder-configurer.xml ├── prototype-bean.xml ├── spring.xml ├── type-conversion-second-part.xml └── value-annotation.xml /.gitignore: -------------------------------------------------------------------------------- 1 | out/ 2 | target/ 3 | .idea/ 4 | .idea_modules/ 5 | *.iml 6 | *.ipr 7 | *.iws -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mini-spring 2 | [![Build Status](https://img.shields.io/badge/build-passing-brightgreen)](https://github.com/DerekYRC/mini-spring) 3 | [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) 4 | [![Stars](https://img.shields.io/github/stars/DerekYRC/mini-spring)](https://img.shields.io/github/stars/DerekYRC/mini-spring) 5 | [![Forks](https://img.shields.io/github/forks/DerekYRC/mini-spring)](https://img.shields.io/github/forks/DerekYRC/mini-spring) 6 | 7 | **[English](./README_en.md) | 简体中文** 8 | 9 | **姊妹版:**[**mini-spring-cloud**](https://github.com/DerekYRC/mini-spring-cloud) **(简化版的spring cloud框架)** 10 | 11 | ## 关于 12 | 13 | **mini-spring**是简化版的spring框架,能帮助你快速熟悉spring源码和掌握spring的核心原理。抽取了spring的核心逻辑,**代码极度简化,保留spring的核心功能**,如IoC和AOP、资源加载器、事件监听器、类型转换、容器扩展点、bean生命周期和作用域、应用上下文等核心功能。 14 | 15 | 如果本项目能帮助到你,请给个**STAR,谢谢!!!** 16 | 17 | ## 功能 18 | #### 基础篇 19 | * [IoC](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#基础篇IoC) 20 | * [实现一个简单的容器](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#最简单的bean容器) 21 | * [BeanDefinition和BeanDefinitionRegistry](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#BeanDefinition和BeanDefinitionRegistry) 22 | * [Bean实例化策略InstantiationStrategy](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#Bean实例化策略InstantiationStrategy) 23 | * [为bean填充属性](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#为bean填充属性) 24 | * [为bean注入bean](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#为bean注入bean) 25 | * [资源和资源加载器](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#资源和资源加载器) 26 | * [在xml文件中定义bean](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#在xml文件中定义bean) 27 | * [容器扩展机制BeanFactoryPostProcess和BeanPostProcessor](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#BeanFactoryPostProcess和BeanPostProcessor) 28 | * [应用上下文ApplicationContext](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#应用上下文ApplicationContext) 29 | * [bean的初始化和销毁方法](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#bean的初始化和销毁方法) 30 | * [Aware接口](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#Aware接口) 31 | * [bean作用域,增加prototype的支持](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#bean作用域增加prototype的支持) 32 | * [FactoryBean](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#FactoryBean) 33 | * [容器事件和事件监听器](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#容器事件和事件监听器) 34 | * [AOP](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#基础篇AOP) 35 | * [切点表达式](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#切点表达式) 36 | * [基于JDK的动态代理](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#基于JDK的动态代理) 37 | * [基于CGLIB的动态代理](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#基于CGLIB的动态代理) 38 | * [AOP代理工厂ProxyFactory](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#AOP代理工厂) 39 | * [几种常用的Advice: BeforeAdvice/AfterAdvice/AfterReturningAdvice/ThrowsAdvice](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#几种常用的AdviceBeforeAdviceAfterAdviceAfterReturningAdviceThrowsAdvice) 40 | * [PointcutAdvisor:Pointcut和Advice的组合](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#pointcutadvisorpointcut和advice的组合) 41 | * [动态代理融入bean生命周期](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#动态代理融入bean生命周期) 42 | 43 | #### 扩展篇 44 | * [PropertyPlaceholderConfigurer](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#propertyplaceholderconfigurer) 45 | * [包扫描](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#包扫描) 46 | * [@Value注解](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#value注解) 47 | * [基于注解@Autowired的依赖注入](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#autowired注解) 48 | * [类型转换(一)](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#类型转换一) 49 | * [类型转换(二)](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#类型转换二) 50 | 51 | #### 高级篇 52 | * [解决循环依赖问题(一):没有代理对象](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#解决循环依赖问题一没有代理对象) 53 | * [解决循环依赖问题(二):有代理对象](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#解决循环依赖问题二有代理对象) 54 | 55 | #### 其他 56 | * [没有为代理bean设置属性(discovered and fixed by kerwin89)](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#bug-fix没有为代理bean设置属性discovered-and-fixed-by-kerwin89) 57 | * [支持懒加载和多切面增强(by zqczgl)](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#支持懒加载和多切面增强by-zqczgl) 58 | 59 | ## 使用方法 60 | 阅读[changelog.md](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md) 61 | 62 | [视频教程(完整版)](https://www.bilibili.com/video/BV1nb4y1A7YJ) 63 | 64 | ## 提问 65 | [**点此提问**](https://github.com/DerekYRC/mini-spring/issues/4) 66 | 67 | ## 贡献 68 | 欢迎Pull Request 69 | 70 | ## 关于我 71 | [**点此了解**](https://github.com/DerekYRC) 72 | 73 | 手机/微信:**15975984828** 邮箱:**15975984828@163.com** 74 | 75 | ## Star History 76 | 77 | [![Star History Chart](https://api.star-history.com/svg?repos=DerekYRC/mini-spring&type=Date)](https://star-history.com/#DerekYRC/mini-spring&Date) 78 | 79 | ## 版权说明 80 | 未取得本人书面许可,不得将该项目用于商业用途 81 | 82 | ## 参考 83 | - [《Spring源码深度解析》](https://book.douban.com/subject/25866350/) 84 | - [《Spring 源码解析》](http://svip.iocoder.cn/categories/Spring) 85 | - [《精通Spring 4.x》](https://book.douban.com/subject/26952826/) 86 | - [《tiny-spring》](https://github.com/code4craft/tiny-spring) 87 | -------------------------------------------------------------------------------- /README_en.md: -------------------------------------------------------------------------------- 1 | # mini-spring 2 | [![Build Status](https://img.shields.io/badge/build-passing-brightgreen)](https://github.com/DerekYRC/mini-spring) 3 | [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) 4 | [![Stars](https://img.shields.io/github/stars/DerekYRC/mini-spring)](https://img.shields.io/github/stars/DerekYRC/mini-spring) 5 | [![Forks](https://img.shields.io/github/forks/DerekYRC/mini-spring)](https://img.shields.io/github/forks/DerekYRC/mini-spring) 6 | 7 | **English | [简体中文](./README.md)** 8 | 9 | [**mini-spring-cloud**](https://github.com/DerekYRC/mini-spring-cloud) **(simplified version of the Spring Cloud framework)** 10 | 11 | ## About 12 | 13 | The **mini-spring** is a simplified version of the Spring framework that will help you quickly get familiar with the Spring source code and grasp the core principles of Spring. The core logic of Spring is extracted, the code is extremely simplified, and the core functions of Spring, such as IoC and AOP, resource loaders, event listeners, type conversion, container extension points, bean life cycle and scope, and application context, are retained. 14 | 15 | If this project can help you, please **STAR the project, thank you!!!** 16 | 17 | ## Contents 18 | #### Basics 19 | * [IoC](#Ioc) 20 | * [Implement a simple container](#实现一个简单的容器) 21 | * [BeanDefinition and BeanDefinitionRegistry](#BeanDefinition和BeanDefinitionRegistry) 22 | * [Bean Instantiation Strategy](#Bean实例化策略InstantiationStrategy) 23 | * [Populate bean with property values](#为bean填充属性) 24 | * [Populate bean with bean](#为bean注入bean) 25 | * [Resource and ResourceLoader](#资源和资源加载器) 26 | * [Define the bean in the XML file](#在xml文件中定义bean) 27 | * [Container extension mechanism:BeanFactoryPostProcess and BeanPostProcessor](#容器扩展机制BeanFactoryPostProcess和BeanPostProcessor) 28 | * [ApplicationContext](#应用上下文ApplicationContext) 29 | * [Init method and destroy method of bean](#bean的初始化和销毁方法) 30 | * [Aware interface](#Aware接口) 31 | * [Bean scope, added prototype support](#bean作用域,增加prototype的支持) 32 | * [FactoryBean](#FactoryBean) 33 | * [Event and event listener](#容器事件和事件监听器) 34 | * [AOP](#AOP) 35 | * [Pointcut expression](#切点表达式) 36 | * [JDK-based dynamic proxy](#基于JDK的动态代理) 37 | * [CGLIB-based dynamic proxy](#基于CGLIB的动态代理) 38 | * [AOP ProxyFactory](#AOP代理工厂ProxyFactory) 39 | * [Common Advice: BeforeAdvice/AfterAdvice/AfterReturningAdvice/ThrowsAdvice](#几种常用的Advice) 40 | * [PointcutAdvisor:A combination of Pointcut and Advice](#PointcutAdvisor:Pointcut和Advice的组合) 41 | * [Dynamic proxies are integrated into the bean lifecycle](#动态代理融入bean生命周期) 42 | 43 | 44 | #### Expanding 45 | * [PropertyPlaceholderConfigurer](#PropertyPlaceholderConfigurer) 46 | * [Package scan](#包扫描) 47 | * [Value annotation](#Value) 48 | * [Autowired annotation](#Autowired) 49 | * [Type conversion(first part)](#类型转换一) 50 | * [Type conversion(second part)](#类型转换二) 51 | 52 | #### Advanced 53 | * [Solve the problem of circular dependencies(first part): without proxy bean](#解决循环依赖问题一) 54 | * [Solve the problem of circular dependencies(second part): with proxy bean](#解决循环依赖问题二) 55 | 56 | #### Bug fix 57 | * [populate proxy bean with property values(discovered and fixed by kerwin89)](#没有为代理bean设置属性) 58 | 59 | ## Usage 60 | Each function point corresponds to a branch. Switch to the branch corresponding to the function point to see the new function. The incremental change point is described in the [changelog.md](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md) file. 61 | 62 | ## Contributing 63 | Any contributions you make are greatly appreciated. 64 | 65 | ## Contact 66 | Please feel free to ask me any questions related to mini-spring and other technologies. My email is **15521077528@163.com**. 67 | 68 | ## Reference 69 | - [《Spring源码深度解析》](https://book.douban.com/subject/25866350/) 70 | - [《精通Spring 4.x》](https://book.douban.com/subject/26952826/) 71 | - [tiny-spring](https://github.com/code4craft/tiny-spring) 72 | -------------------------------------------------------------------------------- /assets/application-context-life-cycle.drawio: -------------------------------------------------------------------------------- 1 | 7ZnbcpswEIafRpfpmJMQl2CTtDPJTDqetkluOopRgBYjV8ixnaevJCQDPiRup3Zd11dGv1Yg7e4nwRo4/fH8iuFJdkMTUgC7l8yBMwC2bfegLX6ksqgVy0JaSVmeaK0RhvkL0WJPq9M8IVXHkFNa8HzSFUe0LMmIdzTMGJ11zZ5o0X3qBKdkTRiOcLGufskTntUqsv1Gf0/yNDNPtmBQ94yxMdYrqTKc0FlLcmLg9BmlvL4az/ukkN4zfqnHXW7pXU6MkZLvMuDl68tt+uFj+HmYk/wxCL2H5NMF0nPjC7Ngkoj16yZlPKMpLXERN2rE6LRMiLxrT7Qam2tKJ0K0hPiNcL7QwcRTToWU8XGhe8k853dy+DtPt+5bPYO5vrNqLEyj5GzRGiSb9+2+ZphqmXHrXtKOq+iUjcgrrjHZhllK+Ct2Op+l31oP0DG4InRMxHyEASMF5vlzN6+wTs90addEUFzoIP5CQPV9n3Ex1U8CNizE/KMnKjzQDjX8MaWm46JSwQqFgYUm86ZTXKX6V92lmuDSaHc31yCGIIAA+SB2QRSBCBpDMfu2bUuuJ2LklfRrkkvmwyzLORlOsArUTGwx3USqOKPfSZ8WlKnRDrIfHQjlmvKiaOmJR1Di6rWa7N5AkPEeYZzMX42m2eGQptvsb4b2WbNZWFBrWWujcHt7SoDgTPQbpL5JtHNURNt7IjoiuByQp7zMeU7LU+XT7fJp99b5XNochE/zYnMGdCt4bwIKjwpQZ4+AXuIRp2xxSyt+y+iIVJVARh61lyCM1eErroP/AuXl0WpQRusou+igKNtnlLf5xt0RZf+oUHb3iPIKwx5AAUADEPsgGiiYPRC6ALlSCXoAwRPleHkEa45dd51jxz4ox96Z422+8Xbk2HKPCmTvkCBLWuMzyHDDu/WBQbbWfHqkIP8+kHBHII+LR7gnHh8Fjwq4GASxejGOAYrU6dqXhakTJW+l6uTAv111spx/hbzDH6H+jsR6R0Wsvydi5UerePMNfRAjEFqC05phcVaG6tAU6CIQDBTVfgfmutYcBfIickDgnSreK0Urb0NR+cBFq319GKkteyDLGTIBXBCiE42ps1K9gBuqF3+oeCGazb+Kqq/156wT/wQ= -------------------------------------------------------------------------------- /assets/application-context-life-cycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DerekYRC/mini-spring/0a14861c7be1a942a6cfe037ba012a59dfca2755/assets/application-context-life-cycle.png -------------------------------------------------------------------------------- /assets/auto-proxy.drawio: -------------------------------------------------------------------------------- 1 | 7Vxbs5o6FP41efSMXIVHUGw703ZsndPbSwclG9Mi4UDc6v71J4EgF6Oy94gy6pNkkUDIl2+tlZUsgTJcbt7FbrT4hD0YALnvbYAyArIsG4ZJf5hkyyWKJmUSP0ZeJisJpugFcmGfS1fIg0mlIsE4ICiqCuc4DOGcVGRuHON1tdoTDqpvjVwf7gmmczfYl35HHllkUkMeFPL3EPmL/M2Szr946eaV+ZckC9fD65JIcYAyjDEm2dVyM4QBG718XLJ24wN3dx2LYUiaNHj5/TLxP3yxvk0RRDPT0n55//YM3jeyzT8YevT7eRHHZIF9HLqBU0jtGK9CD7Kn9mmpqPMR44gKJSr8AwnZcjDdFcFUtCDLgN+FG0R+sOb/aLz0s3RntOFPTgvbvBCSeFtqxIo/y/eKZmkpb7c/SnzgEryK5/DI0OSzzY19SI7Uk7N6bNxKL+AYvIN4CWl/aIUYBi5Bz9V55fLp6e/qFQjSCw7iKwDlz312gxV/E5D1gPbffsJ0BMpQ6/+tcH6jl6RgWbSCZESb4ia98vlv+pQkcsNc9uPTR+DowNSBMQCOCmwb2Hpekfa+XLckzjqSi2vTr5hcbD6sF4jAaeSmQK2piqlOpITE+C8c4gDHaWvFkGeKrrNvQkFQknsaNDyVf2s+uwUMykcPxgRujqK503Cc3Vy/9VReXhfKQtK5bFFSFHm9s08A88HoizGVN51glFKLzwlFr84JSa5hnakU3qoG964bb58BcksqwIZuOIJPKEQE4fBWCa1WwRPweSc7N59h/MdYfJ3+GOPo17PzbWPaxixH89b5XCPl2wiu7Jts4Zhe1UIrLdJz7M4JjrcTnJBJjOcwSShhmGUeA8tJbTW9Nu+CyDutW9fCJSarxiUts3QnVH4Lc9WGzvagU8622iKVaxzWAF1KGyPgDIA9SsmsAUsFhsokZh8Y+o3yWO7XDLLAIivyRXmsPXh8aGy0hjyW1E4RWbskkRlbnQeR9f4FiRwQ3Av/Pvuu6283E8v7lETTe3Gt38JjfZ/HwiGUOkVjvSUazyiNU546wHRSf9oBhp0a5SELf90oYWuxrV35arEtSXkw9oRnfNLyatdirJ54MzR4n3xxPg8nymf960vP7+0Dej64SmAV0J2AS6qAVWB3CbiEA9QtBTtoScGy0ARd31gD4BjAkqhazVQu9Yis1DWimtYA5ihVwoOK7s02IGyTXdgKMLVb1ca1wKQmiGe0Fpk0e44Me847SfPncbz47utrqZdv0T608eH1TZnf4kHsFL+ltiIaqdM0YnFIxmkVWMaN0lSphR11gdPUVtRRaEDUoyQNcXibrDxmTE8aXblTPlJbW/ofWPzfDdALCn0WqKC0cJ8IjCcxjuh8RzCZQnKjNO3thRUFPG0tGiGE+XhU8dxElcAbvOM+OL93fIyA3d0OONbrFoynwU7YWFYeg7BSc2oyl/k1njHb8OvRT11g715orenXprUk7Q1qqwa4K6te4WA0XfWa1+K10Ed/HJJ8DaDCIeyWor5aGMNkax/qadB61hgY0t1GLwyBu9Va9EKsl4/v/tzXwshsqJfzkE9HeGy2xOMRSiKcuLMA8nWRBxmFtjdKzj2vybjkGQvxRDu+03Nfq6GcdSfp2S0rm3f7suuh0yaWk/nOVkKmYL/gssctHpu3B4emaa7R1U5NHet1myeZrTUdTcqTBJKS9EY5W6escsnghRDh65507EooQzg0TU8sd4uybe3vWVEUoLnL8gmGtD7ckBJz92/eKIH1BmeV1TOtcvHsD8t3lvuBO4NBjqV8KpYllz6AT5g7N8jHtuU743HTIgf8FXHLq6aCvmlJ1Yb2borvZeKWaVMrjt1tqULEUkGT0pNrGaWaVluf92up/ifqS/1qA3qRdaGYaq/LOz02pme3LckcRxA4Y2APgTlubDoWeDlbJafNxiHjcNicnMFS1I+JDASunuiYiHEGT08IXlsZEAkK/QCS5mmGqXtQASiG9CUsGMdZz3RO9tr0thsgP6TXc4oGpFDZDAXqbgQWv7FEnpfqNk4z+hrNBtqohj2PKVVhFwaazoF/LUfc0PbxNwX411PJz4Z/W0fnoxgTTLaUwA/8S/irdf4L9kMuir9oS6zuPAQBihJ4WqO6SZT9Fc8T2rBB64aKNS+oYoVZ53cS/3ptJv/hDP0Gq2u9HXe7GaDtHcxLiBsSlK6Y03W0II8wdYeMYXrcZ8xC3dnBWuogsU1og6USZn/JYylFZiGLl4/TWLgBbIltUXd2Ib5HdMFEOsj9evK/LMg1PFfyPy0Wf+KV+dLFf6Epzv8= -------------------------------------------------------------------------------- /assets/auto-proxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DerekYRC/mini-spring/0a14861c7be1a942a6cfe037ba012a59dfca2755/assets/auto-proxy.png -------------------------------------------------------------------------------- /assets/aware-interface.drawio: -------------------------------------------------------------------------------- 1 | 7Ztfk6I4EMA/TR69kv/wiMrsbtXOlnvW3e3ey1WUDOYWCQdx1Pn0l2AQEERnSpASnySdAKE7v3SnE4EyXm0/RTBcPhMX+UAeulugTIAsy6ZpsR8u2e0lkmTKe4kXYVfIMsEMvyEhHArpGrsoLjSkhPgUh0XhggQBWtCCDEYR2RSbvRC/+NYQeqgkmC2gX5b+hV263EtN2cjknxH2lumbJV188QqmjcWXxEvokk1OpDhAGUeE0P3VajtGPtdeqpf9fU8nag8di1BAL7nh7Z+3qfflu/3nDCM8t2ztb/ePgSn6RnfpByOXfb8okoguiUcC6DuZdBSRdeAi/tQhK2VtvhISMqHEhP8iSnfCmHBNCRMt6coXtWiL6Q9++2+aKP3M1Uy24slJYZcWAhrtcjfx4s98XXZbUkrvK2tJKC4m62iBalSTjjYYeYjWtBPjmest9wJhg0+IrBDrD2sQIR9S/FocV1AMT+/QLrMguxBGfIdBxXNfob8WbwKy7rP+j14I00De1Pp/a5JWDOLEWDZrIJnhNqtkV574TZ4ShzBIZT+evwJHB5YOTAM4KhiNwEhPG7Le59vmxPuOpOKj4ZcNLj4eNktM0SyEiaE2bIopDqSYRuQXGhOfRMndiinPFV3n34R9Pyd3NWS6qvjWdHRXEJRqD0UUbWuteZjhBN1iflNFcZPNFZIuZMvcPJG2u7r9rQfQZ0A9C7TSKaDlhoAeIRhM0AsOMMUkuFc81SKeklzm89CmFT7TuOYB6EnwzgKqdwpQpUFAn+CCkmg3JTGdRmSB4pghwz3tE7CdxPeya6sXKB/QFSjLwzLKqtkqyvID5VO6US9E2egUymqDKB8xrAG2NDYnwDHAaJLArAFbBabKJdYQmPqdcnzgNo2YK0JmRW6VY+3B8SndaBdyLKmdAllrE2ROq/MAWa9wyI2B7FMyCH69ehB6u+3Udp/jcJYule6d4yPGPga2Xga7Uqc3xVhvCOM5wzjh1AGWk8TTDjBHiVMe83TWnQJ7lKs6lG+WrJKUfhD7EUCNCz2vdivHq8fuHBuf4+/Ot/FU+ab//jbwBmWDXs9cOWNlpjtjLqlgrMx2bZirUkFSp+Iko6EJlqcm2PrGNoBjAlti0+p+ymURkZ2ERmymNYE1SSZhozD37jcURha/GCnA0u51Nj5KTWptpiYrh2b9XmBAgh7NvlJFAqNSad1KYEhNZTCSIGnC846cYRXY5p1iqRylGfWKIKmpLGPlAFP7SWWd8zwLpdypmKipLfkvPN8PffyGA48nJhgW8IWiaBqRkI13jOIZoneK6aCURqzgtLHsQ6WZ67OI1wZVAh+Ihofg+tFwHYDdTf/X9boB52nyEzK2neYc7MSdWjxEfk8kzDf4BuxTl8TtC9aafmusJamk1EYdcFdWuXXR7lkHbHWK65utci0eKjPHxNrZT8CUeru4NSowbndxe2azvl9xtHUhxulhpY5wbDXE8QTHIYnh3EcijHYRR2h3p3CWnKxRkXpq2cnWbwT0K3hOqetu7qm22+2Gz+ddrIC5Z4GzefPd+J7s7b13N/70LvsF62W1JcDrOtnkQVd7w5THOIkRzUm7y2wJ0ArzX3yARmlzrVtp4dsehGtt5XsVZC894XpTZJvaDrLD0McLyI+bj1l7tKU5csuVdwqwfsFRVvVKq1xWzP4qmtTl/nGrOP8D -------------------------------------------------------------------------------- /assets/aware-interface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DerekYRC/mini-spring/0a14861c7be1a942a6cfe037ba012a59dfca2755/assets/aware-interface.png -------------------------------------------------------------------------------- /assets/bean-definition-and-bean-definition-registry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DerekYRC/mini-spring/0a14861c7be1a942a6cfe037ba012a59dfca2755/assets/bean-definition-and-bean-definition-registry.png -------------------------------------------------------------------------------- /assets/chainProceed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DerekYRC/mini-spring/0a14861c7be1a942a6cfe037ba012a59dfca2755/assets/chainProceed.png -------------------------------------------------------------------------------- /assets/init-and-destroy-method.drawio: -------------------------------------------------------------------------------- 1 | 7Ztbs9o2EIB/jR7p4Lv8aINPkpkkQ8q0TfrSMVjHVmssaotw+fWVjIRtbC5JseEAT1gryUhafburFQBtMFu9S/159IkEKAZqP1gBbQhUVYXQZh9cst5KFAWqW0mY4kDICsEYb5AQ9oV0gQOUVRpSQmKK51XhlCQJmtKKzE9Tsqw2eyVx9VvnfohqgvHUj+vSP3BAo60UqlYhf49wGMlvVkwx45kvG4uZZJEfkGVJpHlAG6SE0O3TbDVAMV89uS7bfi8HancDS1FCz+mw+WszCj98cX4fY4QntmP8GfzWg2JsdC0njAI2f1EkKY1ISBI/9gqpm5JFEiD+1j4rFW0+EjJnQoUJ/0aUroUy/QUlTBTRWSxq0QrTr7z7L4YofSvVDFfizXlhLQsJTdelTrz4rVxXdMtLsl99lcTCZWSRTtGRpZG7zU9DRI+0E/uZr1vpC4QO3iEyQ2w8rEGKYp/i79V95YvtGe7aFRpkD0KJP6BQ8d7vfrwQ3wRUM2bjd18JW4Gyqs1/F0RW9LJcWQ5roMD5qqhkT6H4zN+Szf1Eyr5++gg8E9gmgBbwdOC6wDVlQzb6ctuSeDsQKd7bfsXm4vthGWGKxnM/V9SSmZjqRspoSv5BAxKTNO+tQXWimSafE47jkjwwEAx0MVe5uxsIkquHUopWR7W5s3CCbmnfJO3LwlgoppBFJUOh91vaAPaT6BOkniRauymi1ZaIdpGfDNErTjDFJLlXPvUqn2q/zueuTSd8ysDmCehB8E4Cat4UoFqLgL74U0rS9YhkdJSSKcoyhgx3tS/A8XLny57th0B551olyrCOsg47RVl9onxobfQzUbZuCmW9RZT3GDYAOxvDIfAs4A5zmA3g6ADqXGL3ATTvlOOdCxYc63qdY03tlGPjyfGhtTHO5FjRbwpko0uQOa3eE2SzIbbuGGSltqY3CvLPA2meCeRt8Wi2xOOE8ZgD5wHbywNjD0A3964Dnpi6U/L2sk6aee2sk6K9FfK6d6HWmcQa1yLWzIIJtt5nX7zPg5H22fx10wt7dYVeTl0lZRWqO6EupaKsQndH1bW3lhfTX+OKXdXAWi0ZWJ5jYAcVxwIeBI7CzOrW5LLQxsljHGZpIbCHuRG2KrZ3ezXg2vzB1YBt3Ks13ssxGg13AK3lGBt34vFbvYQkb9T6XgRnpSE10biK1jV5VtpKReRB0pAnEDnDOnDgnWKp7eULzYZ8YVvpwsb9pD+pPOE8z4BSvWZM1Nbl+geeuPdjvMFJyDMMDAv/laJ0lJI52+8YZWNEbxfTGpMNW+Agpr1aPrCB09bSCI1qPp4OvDSoCviJaLgPOoiGDwN4bmL/WqCqrTlPyH/r4jgy5+Dk7tTmIfKPRML8pq7HphqR4FGwNhpyFN1ifSI7eHEHfLOn3MPR7hkO2L4m11c75do8VGaOibVzXgBU3tLh9n9xvH+4tRow7vZwe+LW/cHjaPtMjJV+s9q74dhuieMhzuYk8ycxEmF0gDhC6zuFs+ZkrYbUU8dO9vhFwIMHz/LHfzeTezo6ym7D59MuVsD8YIEzbPFanRWLP6DkdaX/8Wjefw== -------------------------------------------------------------------------------- /assets/init-and-destroy-method.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DerekYRC/mini-spring/0a14861c7be1a942a6cfe037ba012a59dfca2755/assets/init-and-destroy-method.png -------------------------------------------------------------------------------- /assets/instantiation-strategy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DerekYRC/mini-spring/0a14861c7be1a942a6cfe037ba012a59dfca2755/assets/instantiation-strategy.png -------------------------------------------------------------------------------- /assets/populate-proxy-bean-with-property-values.drawio: -------------------------------------------------------------------------------- 1 | 7Vxbd5s4EP41evQeczU8go3b7ml63M3Z3l72YKNgUoIoKLGdX7+SEDEX+ZIUMLX9ZBgkLGbmmxmNRgLK+GH9LnHj5Q3yYAjkobcGygTIsmwYJvmhlA2nKJqUUfwk8DJagXAbPENOHHLqY+DBtNQQIxTiIC4TFyiK4AKXaG6SoFW52R0Ky/8auz6sEW4Xblinfg08vMyohjza0t/DwF/m/yzp/Isf3Lwx/5J06XpoVSApDlDGCUI4u3pYj2FIuZfzJes33fH0ZWAJjPAxHZ7/e575Hz5bX24DGMxNS/vh/Tsw+NjwJv9g6JHv57cowUvko8gNnS3VTtBj5EH61iG527b5iFBMiBIh3kOMN1yY7iNGhLTEDyF/CtcB/ka7/6Xxu++FJ5M1fzO72eQ3EU42hU709nvx2bYbu8v71bnEGZeix2QB97Am1zY38SHe007O2lG+Ff6Ay+AdRA+QjIc0SGDo4uCprFcuV0//pd1WguSCC/EVAuXvfXLDR/5PQNZDMn77DhEOFEWt/3pE+YNByoRlkQaSEa+3D8mVz3/ZW9LYjXLat5uPwNGBqQNjBBwV2DawdUoxDEJchG6aCp7zF5GvK76rQM4GmpMr6rlVPqovq2WA4W3sMkGuiAkqK1qKE/QTjlGIEtZbMeS5ouv0m4MwLNA9DRqeynmRa78AYTl3YYLheq+0cwuocvRz+zfI71dbY/LSZlkwJDmtcQUxr4jvDMm86wwFDHpcJxS9rBOSXJF1ZnJ4r4q4X4bxdg2QWzIRNnSjCbwLogAHKLoQQHeJZ5jcG8t/br9NUfzjyfmyNm1jnkvziue6oit1Dy5kodQrD660CM+pu8Ao2cxQimcJWsA0JYChnnkKLIf5anJtXgSQX6xu1QoXkKwaXXpm6QrlnbxRjwzGR72CstoilCsY1gCZahsT4IyAPWFg1oClAkOlFHMIDP1McSwPyzjWjTqOFblTHGtXHO/ijXYkjiW1V0DWugQyRatzBbIhCK1bA/JqJt3jX+poejOe/60s081z+HmgXwaOKxh7G7D1OrCFPFVOCWO9JRjPCYwZTh1gOiyedoBhM6c8pumvMwWsUQasLPC8kt6p51UuA7FvAejoSM+rncrx6qk3D0bv08/Op/FM+aT/8zzwB3WBNieugrC2ojsgLqkkrK3suhCXkEH9yl2MWjKwbFHBBNYIOAawJGJWM5NLIiKLhUYaW3OYMCM8KtnebAHCNumFrQBTO1drXElMjvQOM5PmwJHhwHknaf4iSZZffX0lDfIl3Ks13j2/KeJbzMRe4VtqK6PBgqYJzUNSTKvAMs4Upkol7WgK0o5tZR2FDkTdC9IIReeJyn3O9KDTlXsVI7W15P+B5v/dMHgOIp8mKggs3DsMk1mCYqLvAUxvIT5TmA6q2YiRAKetZSOEYt6fVWwaqBJ4Q3Q8BM1Hx/sA2N/lgH2jbsF5GrTCxrLyHITF3KlJQ+bXRMZ0wW9APnWJvEuBtTE8NawlqcbUVh1wX2a9QmYcO+s1T4VrYYx+LaJ8jUCFLOyXoT5ZGsOkcx8S/pN21hQY0sVmLyRROUZr6QuxYZavM6OqwT2cjhz2CshmS0CeBGmMUnceQj4x8iDF0OZM0VkLm6Rhl1UWYk3bv9ZzWfOhHHYH8dkvP5sPu9sZ0WEny9F8YXMhSRIsGbQG6hCjQfTzyXddf7OeWd5NGt8KlvsuMZIWsubY7UgnK5wSlnv8OWtAQrb9hqha3zbyUujY/LaRfQrYZl26tSLcJjYvhbhAPVP7Wytc7TIVJZTwaetW+5KYErLm2Przk1nffaNuHLJWHIfBwqW7Q8akPVzjAnLrD88UwPoRledqQykLNL+nu9vlYejOYZjLUj6UmZQLH8AVpv+euNXYal+RRW9mT+SWC/wVWeiTbux90/S4Det9rHy7yUKzrlaSuJtCg5hGaOnuQE/TqskWtXKyw6EOcrkDucjG8NZ4cB9TG3cu6QLFEDhTYI+BOT3adyzRw/wxPew3dnmH3f6kAVdRrfqRhoJgT1T2U43xG1uzamtHSxpEfgjx8dtGWYBQklACyZ/Q3CrHPbU62d+yx24Y+BG5XhBxQCIrm4qBBByhxR88BJ7HrBsHGvkbzQbapCJ8niEsy12YNmxCAap7/odmXQFMgQJUzwZoTAHa2gsRJwgjvCEQvipAQQHUmgUQLHB1qgCiRc5qABGGQZzCw0bVTePs8KW7YE251hMrK3doZYUnC1zzmTtZc2w+U+8o5j5OoO3VWqbYjXDAps1sMl3fGior8fbehncogaVuZzrNrlQGiDCtt1UYIMxpC+zkOabJXpsKF+f/6yjfjauTLVK0BGq2+KgDQ2YrjA4wx2zNcUL3c293dRt014PJKKZNmmUlQWz6Y4zZsuWYrV9qdLWSXGdLm3a2H3xKX0dfMaJPS72M/DgImxUcZResDpTuTh3mbQRFSf01JDWrIdDKnYbEGEoHLUlT+brjFG90GeFBI5ZEcJiTsJ16SkvS1tlNrw4PLLpR4w+JDn4L1JXoQBGUMHQbHVxIMXAjmBasqgnbaafEdFuLaK/GNN93tflCR5JeBp5VwSEw3eL5Qs5LbQTPgtOdWimQ+S2BtpX5ZuGzQ4Pr4tFNtsSOhNFpxE1C7PMEbfUkGE2Q22zqJBhyuz0zPVvL2h49rzj/Aw== -------------------------------------------------------------------------------- /assets/populate-proxy-bean-with-property-values.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DerekYRC/mini-spring/0a14861c7be1a942a6cfe037ba012a59dfca2755/assets/populate-proxy-bean-with-property-values.png -------------------------------------------------------------------------------- /assets/prototype-bean.drawio: -------------------------------------------------------------------------------- 1 | 7Vxbs5o6FP41efSMXIVHUGw703ZsndPbSwclG9Mi4UDc6v71J4EgF6Oy94gy6pNkkUDIl2+tlZUsgTJcbt7FbrT4hD0YALnvbYAyArIsG4ZJf5hkyyWKJmUSP0ZeJisJpugFcmGfS1fIg0mlIsE4ICiqCuc4DOGcVGRuHON1tdoTDqpvjVwf7gmmczfYl35HHllkUkMeFPL3EPmL/M2Szr946eaV+ZckC9fD65JIcYAyjDEm2dVyM4QBG718XLJ24wN3dx2LYUiaNHj5/TLxP3yxvk0RRDPT0n55//YM3jeyzT8YevT7eRHHZIF9HLqBU0jtGK9CD7Kn9mmpqPMR44gKJSr8AwnZcjDdFcFUtCDLgN+FG0R+sOb/aLz0s3RntOFPTgvbvBCSeFtqxIo/y/eKZmkpb7c/SnzgEryK5/DI0OSzzY19SI7Uk7N6bNxKL+AYvIN4CWl/aIUYBi5Bz9V55fLp6e/qFQjSCw7iKwDlz312gxV/E5D1gPbffsJ0BMpQ6/+tcH6jl6RgWbSCZESb4ia98vlv+pQkcsNc9uPTR+DowNSBMQCOCmwb2Hpekfa+XLckzjqSi2vTr5hcbD6sF4jAaeSmQK2piqlOpITE+C8c4gDHaWvFkGeKrrNvQkFQknsaNDyVf2s+uwUMykcPxgRujqK503Cc3Vy/9VReXhfKQtK5bFFSFHm9s08A88HoizGVN51glFKLzwlFr84JSa5hnakU3qoG964bb58BcksqwIZuOIJPKEQE4fBWCa1WwRPweSc7N59h/MdYfJ3+GOPo17PzbWPaxixH89b5XCPl2wiu7Jts4Zhe1UIrLdJz7M4JjrcTnJBJjOcwSShhmGUeA8tJbTW9Nu+CyDutW9fCJSarxiUts3QnVH4Lc9WGzvagU8622iKVaxzWAF1KGyPgDIA9SsmsAUsFhsokZh8Y+o3yWO7XDLLAIivyRXmsPXh8aGy0hjyW1E4RWbskkRlbnQeR9f4FiRwQ3Av/Pvuu6283E8v7lETTe3Gt38JjfZ/HwiGUOkVjvSUazyiNU546wHRSf9oBhp0a5SELf90oYWuxrV35arEtSXkw9oRnfNLyatdirJ54MzR4n3xxPg8nymf960vP7+0Dej64SmAV0J2AS6qAVWB3CbiEA9QtBTtoScGy0ARd31gD4BjAkqhazVQu9Yis1DWimtYA5ihVwoOK7s02IGyTXdgKMLVb1ca1wKQmiGe0Fpk0e44Me847SfPncbz47utrqZdv0T608eH1TZnf4kHsFL+ltiIaqdM0YnFIxmkVWMaN0lSphR11gdPUVtRRaEDUoyQNcXibrDxmTE8aXblTPlJbW/ofWPzfDdALCn0WqKC0cJ8IjCcxjuh8RzCZQnKjNO3thRUFPG0tGiGE+XhU8dxElcAbvOM+OL93fIyA3d0OONbrFoynwU7YWFYeg7BSc2oyl/k1njHb8OvRT11g715orenXprUk7Q1qqwa4K6te4WA0XfWa1+K10Ed/HJJ8DaDCIeyWor5aGMNkax/qadB61hgY0t1GLwyBu9Va9EKsl4/v/tzXwshsqJfzkE9HeGy2xOMRSiKcuLMA8nWRBxmFtjdKzj2vybjkGQvxRDu+03Nfq6GcdSfp2S0rm3f7suuh0yaWk/nOVkKmYL/gssctHpu3B4emaa7R1U5NHet1myeZrTUdTcqTBJKS9EY5W6escsnghRDh65507EooQzg0TU8sd4uybe3vWVEUoLnL8gmGtD7ckBJz92/eKIH1BmeV1TOtcvHsD8t3lvuBO4NBjqV8KpYllz6AT5g7N8jHtuU743HTIgf8FXHLq6aCvmlJ1Yb2borvZeKWaVMrjt1tqULEUkGT0pNrGaWaVluf92up/ifqS/1qA3qRdaGYaq/LOz02pme3LckcRxA4Y2APgTlubDoWeDlbJafNxiHjcNicnMFS1I+JDASunuiYiHEGT08IXlsZEAkK/QCS5mmGqXtQASiG9CUsGMdZz3RO9tr0thsgP6TXc4oGpFDZDAXqbgQWv7FEnpfqNk4z+hrNBtqohj2PKVVhFwaazoF/LUfc0PbxNwX411PJz4Z/W0fnoxgTTLaUwA/8S/irdf4L9kMuir9oS6zuPAQBihJ4WqO6SZT9Fc8T2rBB64aKNS+oYoVZ53cS/3ptJv/hDP0Gq2u9HXe7GaDtHcxLiBsSlK6Y03W0II8wdYeMYXrcZ8xC3dnBWuogsU1og6USZn/JYylFZiGLl4/TWLgBbIltUXd2Ib5HdMFEOsj9evK/LMg1PFfyPy0Wf+KV+dLFf6Epzv8= -------------------------------------------------------------------------------- /assets/prototype-bean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DerekYRC/mini-spring/0a14861c7be1a942a6cfe037ba012a59dfca2755/assets/prototype-bean.png -------------------------------------------------------------------------------- /assets/resource.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DerekYRC/mini-spring/0a14861c7be1a942a6cfe037ba012a59dfca2755/assets/resource.png -------------------------------------------------------------------------------- /assets/spring-framework.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DerekYRC/mini-spring/0a14861c7be1a942a6cfe037ba012a59dfca2755/assets/spring-framework.png -------------------------------------------------------------------------------- /assets/xml-file-define-bean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DerekYRC/mini-spring/0a14861c7be1a942a6cfe037ba012a59dfca2755/assets/xml-file-define-bean.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 4.0.0 6 | 7 | org.springframework 8 | mini-spring 9 | 1.0-SNAPSHOT 10 | mini-spring 11 | 12 | https://github.com/DerekYRC/mini-spring 13 | 14 | 15 | UTF-8 16 | 1.8 17 | 1.8 18 | 19 | 20 | 21 | 22 | cglib 23 | cglib-nodep 24 | 3.3.0 25 | 26 | 27 | 28 | aopalliance 29 | aopalliance 30 | 1.0 31 | 32 | 33 | 34 | org.aspectj 35 | aspectjweaver 36 | 1.8.0 37 | 38 | 39 | 40 | org.dom4j 41 | dom4j 42 | 2.1.3 43 | 44 | 45 | 46 | cn.hutool 47 | hutool-all 48 | 5.5.0 49 | 50 | 51 | 52 | junit 53 | junit 54 | 4.11 55 | test 56 | 57 | 58 | 59 | org.assertj 60 | assertj-core 61 | 3.11.1 62 | test 63 | 64 | 65 | 66 | cglib 67 | cglib 68 | 3.3.0 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/aop/AdvisedSupport.java: -------------------------------------------------------------------------------- 1 | package org.springframework.aop; 2 | 3 | import org.aopalliance.intercept.MethodInterceptor; 4 | import org.springframework.aop.framework.AdvisorChainFactory; 5 | import org.springframework.aop.framework.DefaultAdvisorChainFactory; 6 | 7 | import java.lang.reflect.Method; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import java.util.Map; 11 | import java.util.concurrent.ConcurrentHashMap; 12 | 13 | /** 14 | * @author zqc 15 | * @date 2022/12/16 16 | */ 17 | public class AdvisedSupport { 18 | 19 | //是否使用cglib代理 20 | private boolean proxyTargetClass = true; 21 | 22 | private TargetSource targetSource; 23 | 24 | 25 | private MethodMatcher methodMatcher; 26 | 27 | private transient Map> methodCache; 28 | 29 | AdvisorChainFactory advisorChainFactory = new DefaultAdvisorChainFactory(); 30 | 31 | private List advisors = new ArrayList<>(); 32 | 33 | public AdvisedSupport() { 34 | this.methodCache = new ConcurrentHashMap<>(32); 35 | } 36 | public boolean isProxyTargetClass() { 37 | return proxyTargetClass; 38 | } 39 | 40 | public void setProxyTargetClass(boolean proxyTargetClass) { 41 | this.proxyTargetClass = proxyTargetClass; 42 | } 43 | 44 | public void addAdvisor(Advisor advisor) { 45 | advisors.add(advisor); 46 | } 47 | 48 | public List getAdvisors() { 49 | return advisors; 50 | } 51 | 52 | public TargetSource getTargetSource() { 53 | return targetSource; 54 | } 55 | 56 | public void setTargetSource(TargetSource targetSource) { 57 | this.targetSource = targetSource; 58 | } 59 | 60 | 61 | public MethodMatcher getMethodMatcher() { 62 | return methodMatcher; 63 | } 64 | 65 | public void setMethodMatcher(MethodMatcher methodMatcher) { 66 | this.methodMatcher = methodMatcher; 67 | } 68 | /** 69 | * 用来返回方法的拦截器链 70 | */ 71 | public List getInterceptorsAndDynamicInterceptionAdvice(Method method, Class targetClass) { 72 | Integer cacheKey=method.hashCode(); 73 | List cached = this.methodCache.get(cacheKey); 74 | if (cached == null) { 75 | cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice( 76 | this, method, targetClass); 77 | this.methodCache.put(cacheKey, cached); 78 | } 79 | return cached; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/aop/Advisor.java: -------------------------------------------------------------------------------- 1 | package org.springframework.aop; 2 | 3 | import org.aopalliance.aop.Advice; 4 | 5 | /** 6 | * @author derekyi 7 | * @date 2020/12/6 8 | */ 9 | public interface Advisor { 10 | 11 | Advice getAdvice(); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/aop/AfterAdvice.java: -------------------------------------------------------------------------------- 1 | package org.springframework.aop; 2 | 3 | import org.aopalliance.aop.Advice; 4 | 5 | /** 6 | * 后置增强 7 | * 8 | * @author zqc 9 | * @date 2022/12/16 10 | */ 11 | public interface AfterAdvice extends Advice { 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/aop/AfterReturningAdvice.java: -------------------------------------------------------------------------------- 1 | package org.springframework.aop; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | /** 6 | * 后置增强 7 | * 8 | * @author zqc 9 | * @date 2022/12/16 10 | */ 11 | public interface AfterReturningAdvice extends AfterAdvice { 12 | 13 | void afterReturning( Object returnValue, Method method, Object[] args, Object target) throws Throwable; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/aop/BeforeAdvice.java: -------------------------------------------------------------------------------- 1 | package org.springframework.aop; 2 | 3 | import org.aopalliance.aop.Advice; 4 | 5 | /** 6 | * @author derekyi 7 | * @date 2020/12/6 8 | */ 9 | public interface BeforeAdvice extends Advice { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/aop/ClassFilter.java: -------------------------------------------------------------------------------- 1 | package org.springframework.aop; 2 | 3 | /** 4 | * @author derekyi 5 | * @date 2020/12/5 6 | */ 7 | public interface ClassFilter { 8 | 9 | boolean matches(Class clazz); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/aop/MethodBeforeAdvice.java: -------------------------------------------------------------------------------- 1 | package org.springframework.aop; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | /** 6 | * @author derekyi 7 | * @date 2020/12/6 8 | */ 9 | public interface MethodBeforeAdvice extends BeforeAdvice { 10 | 11 | void before(Method method, Object[] args, Object target) throws Throwable; 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/aop/MethodMatcher.java: -------------------------------------------------------------------------------- 1 | package org.springframework.aop; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | /** 6 | * @author derekyi 7 | * @date 2020/12/5 8 | */ 9 | public interface MethodMatcher { 10 | 11 | boolean matches(Method method, Class targetClass); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/aop/Pointcut.java: -------------------------------------------------------------------------------- 1 | package org.springframework.aop; 2 | 3 | 4 | /** 5 | * 切点抽象 6 | * 7 | * @author derekyi 8 | * @date 2020/12/5 9 | */ 10 | public interface Pointcut { 11 | 12 | ClassFilter getClassFilter(); 13 | 14 | MethodMatcher getMethodMatcher(); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/aop/PointcutAdvisor.java: -------------------------------------------------------------------------------- 1 | package org.springframework.aop; 2 | 3 | /** 4 | * @author derekyi 5 | * @date 2020/12/6 6 | */ 7 | public interface PointcutAdvisor extends Advisor { 8 | 9 | Pointcut getPointcut(); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/aop/TargetSource.java: -------------------------------------------------------------------------------- 1 | package org.springframework.aop; 2 | 3 | /** 4 | * 被代理的目标对象 5 | * 6 | * @author derekyi 7 | * @date 2020/12/6 8 | */ 9 | public class TargetSource { 10 | 11 | private final Object target; 12 | 13 | public TargetSource(Object target) { 14 | this.target = target; 15 | } 16 | 17 | public Class[] getTargetClass() { 18 | return this.target.getClass().getInterfaces(); 19 | } 20 | 21 | public Object getTarget() { 22 | return this.target; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/aop/aspectj/AspectJExpressionPointcut.java: -------------------------------------------------------------------------------- 1 | package org.springframework.aop.aspectj; 2 | 3 | import org.aspectj.weaver.tools.PointcutExpression; 4 | import org.aspectj.weaver.tools.PointcutParser; 5 | import org.aspectj.weaver.tools.PointcutPrimitive; 6 | import org.springframework.aop.ClassFilter; 7 | import org.springframework.aop.MethodMatcher; 8 | import org.springframework.aop.Pointcut; 9 | 10 | import java.lang.reflect.Method; 11 | import java.util.HashSet; 12 | import java.util.Set; 13 | 14 | /** 15 | * @author derekyi 16 | * @date 2020/12/5 17 | */ 18 | public class AspectJExpressionPointcut implements Pointcut, ClassFilter, MethodMatcher { 19 | 20 | private static final Set SUPPORTED_PRIMITIVES = new HashSet(); 21 | 22 | static { 23 | SUPPORTED_PRIMITIVES.add(PointcutPrimitive.EXECUTION); 24 | } 25 | 26 | private final PointcutExpression pointcutExpression; 27 | 28 | public AspectJExpressionPointcut(String expression) { 29 | PointcutParser pointcutParser = PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingSpecifiedClassLoaderForResolution(SUPPORTED_PRIMITIVES, this.getClass().getClassLoader()); 30 | pointcutExpression = pointcutParser.parsePointcutExpression(expression); 31 | } 32 | 33 | @Override 34 | public boolean matches(Class clazz) { 35 | return pointcutExpression.couldMatchJoinPointsInType(clazz); 36 | } 37 | 38 | @Override 39 | public boolean matches(Method method, Class targetClass) { 40 | return pointcutExpression.matchesMethodExecution(method).alwaysMatches(); 41 | } 42 | 43 | @Override 44 | public ClassFilter getClassFilter() { 45 | return this; 46 | } 47 | 48 | @Override 49 | public MethodMatcher getMethodMatcher() { 50 | return this; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/aop/aspectj/AspectJExpressionPointcutAdvisor.java: -------------------------------------------------------------------------------- 1 | package org.springframework.aop.aspectj; 2 | 3 | import org.aopalliance.aop.Advice; 4 | import org.springframework.aop.Pointcut; 5 | import org.springframework.aop.PointcutAdvisor; 6 | 7 | /** 8 | * aspectJ表达式的advisor 9 | * 10 | * @author derekyi 11 | * @date 2020/12/6 12 | */ 13 | public class AspectJExpressionPointcutAdvisor implements PointcutAdvisor { 14 | 15 | private AspectJExpressionPointcut pointcut; 16 | 17 | private Advice advice; 18 | 19 | private String expression; 20 | 21 | public void setExpression(String expression) { 22 | this.expression = expression; 23 | } 24 | 25 | @Override 26 | public Pointcut getPointcut() { 27 | if (pointcut == null) { 28 | pointcut = new AspectJExpressionPointcut(expression); 29 | } 30 | return pointcut; 31 | } 32 | 33 | @Override 34 | public Advice getAdvice() { 35 | return advice; 36 | } 37 | 38 | public void setAdvice(Advice advice) { 39 | this.advice = advice; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/aop/framework/AdvisorChainFactory.java: -------------------------------------------------------------------------------- 1 | package org.springframework.aop.framework; 2 | 3 | import org.springframework.aop.AdvisedSupport; 4 | 5 | import java.lang.reflect.Method; 6 | import java.util.List; 7 | 8 | /** 9 | * @author zqc 10 | * @date 2022/12/16 11 | */ 12 | public interface AdvisorChainFactory { 13 | 14 | 15 | List getInterceptorsAndDynamicInterceptionAdvice(AdvisedSupport config, Method method, Class targetClass); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/aop/framework/AopProxy.java: -------------------------------------------------------------------------------- 1 | package org.springframework.aop.framework; 2 | 3 | /** 4 | * AOP代理抽象 5 | * 6 | * @author derekyi 7 | * @date 2020/12/5 8 | */ 9 | public interface AopProxy { 10 | 11 | Object getProxy(); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/aop/framework/CglibAopProxy.java: -------------------------------------------------------------------------------- 1 | package org.springframework.aop.framework; 2 | 3 | import java.lang.reflect.Method; 4 | import java.util.List; 5 | 6 | import net.sf.cglib.proxy.Enhancer; 7 | import net.sf.cglib.proxy.MethodInterceptor; 8 | import net.sf.cglib.proxy.MethodProxy; 9 | 10 | import org.springframework.aop.AdvisedSupport; 11 | 12 | /** 13 | * cglib动态代理 14 | * 15 | * @author zqc 16 | * @date 2022/12/17 17 | */ 18 | public class CglibAopProxy implements AopProxy { 19 | 20 | private final AdvisedSupport advised; 21 | 22 | public CglibAopProxy(AdvisedSupport advised) { 23 | this.advised = advised; 24 | } 25 | 26 | 27 | @Override 28 | public Object getProxy() { 29 | // 创建动态代理增强类 30 | Enhancer enhancer = new Enhancer(); 31 | enhancer.setSuperclass(advised.getTargetSource().getTarget().getClass()); 32 | enhancer.setInterfaces(advised.getTargetSource().getTargetClass()); 33 | enhancer.setCallback(new DynamicAdvisedInterceptor(advised)); 34 | return enhancer.create(); 35 | } 36 | 37 | /** 38 | * 注意此处的MethodInterceptor是cglib中的接口,advised中的MethodInterceptor的AOP联盟中定义的接口,因此定义此类做适配 39 | */ 40 | private static class DynamicAdvisedInterceptor implements MethodInterceptor { 41 | 42 | private final AdvisedSupport advised; 43 | 44 | private DynamicAdvisedInterceptor(AdvisedSupport advised) { 45 | this.advised = advised; 46 | } 47 | 48 | @Override 49 | public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { 50 | // 获取目标对象 51 | Object target = advised.getTargetSource().getTarget(); 52 | Class targetClass = target.getClass(); 53 | Object retVal = null; 54 | List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); 55 | CglibMethodInvocation methodInvocation = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy); 56 | if (chain == null || chain.isEmpty()) { 57 | //代理方法 58 | retVal = methodProxy.invoke(target, args); 59 | } else { 60 | retVal = methodInvocation.proceed(); 61 | } 62 | return retVal; 63 | } 64 | } 65 | 66 | private static class CglibMethodInvocation extends ReflectiveMethodInvocation { 67 | 68 | private final MethodProxy methodProxy; 69 | 70 | public CglibMethodInvocation(Object proxy, Object target, Method method, 71 | Object[] arguments, Class targetClass, 72 | List interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) { 73 | super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers); 74 | this.methodProxy = methodProxy; 75 | } 76 | 77 | @Override 78 | public Object proceed() throws Throwable { 79 | return super.proceed(); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/aop/framework/DefaultAdvisorChainFactory.java: -------------------------------------------------------------------------------- 1 | package org.springframework.aop.framework; 2 | 3 | import org.aopalliance.intercept.MethodInterceptor; 4 | 5 | import org.springframework.aop.AdvisedSupport; 6 | import org.springframework.aop.Advisor; 7 | import org.springframework.aop.MethodMatcher; 8 | import org.springframework.aop.PointcutAdvisor; 9 | 10 | import java.lang.reflect.Method; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | /** 15 | * @author zqc 16 | * @date 2022/12/17 17 | */ 18 | public class DefaultAdvisorChainFactory implements AdvisorChainFactory { 19 | 20 | @Override 21 | public List getInterceptorsAndDynamicInterceptionAdvice(AdvisedSupport config, Method method, Class targetClass) { 22 | Advisor[] advisors = config.getAdvisors().toArray(new Advisor[0]); 23 | List interceptorList = new ArrayList<>(advisors.length); 24 | Class actualClass = (targetClass != null ? targetClass : method.getDeclaringClass()); 25 | for (Advisor advisor : advisors) { 26 | if (advisor instanceof PointcutAdvisor) { 27 | // Add it conditionally. 28 | PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor; 29 | // 校验当前Advisor是否适用于当前对象 30 | if (pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) { 31 | MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher(); 32 | boolean match; 33 | // 校验Advisor是否应用到当前方法上 34 | match = mm.matches(method, actualClass); 35 | if (match) { 36 | MethodInterceptor interceptor = (MethodInterceptor) advisor.getAdvice(); 37 | interceptorList.add(interceptor); 38 | } 39 | } 40 | } 41 | } 42 | return interceptorList; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/aop/framework/JdkDynamicAopProxy.java: -------------------------------------------------------------------------------- 1 | package org.springframework.aop.framework; 2 | 3 | import org.aopalliance.intercept.MethodInvocation; 4 | 5 | import org.springframework.aop.AdvisedSupport; 6 | 7 | import java.lang.reflect.InvocationHandler; 8 | import java.lang.reflect.Method; 9 | import java.lang.reflect.Proxy; 10 | import java.util.List; 11 | 12 | /** 13 | * JDK动态代理 14 | * 15 | * @author zqc 16 | * @date 2022/12/19 17 | */ 18 | public class JdkDynamicAopProxy implements AopProxy, InvocationHandler { 19 | 20 | private final AdvisedSupport advised; 21 | 22 | public JdkDynamicAopProxy(AdvisedSupport advised) { 23 | this.advised = advised; 24 | } 25 | 26 | /** 27 | * 返回代理对象 28 | * 29 | * @return 30 | */ 31 | @Override 32 | public Object getProxy() { 33 | return Proxy.newProxyInstance(getClass().getClassLoader(), advised.getTargetSource().getTargetClass(), this); 34 | } 35 | 36 | @Override 37 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 38 | // 获取目标对象 39 | Object target = advised.getTargetSource().getTarget(); 40 | Class targetClass = target.getClass(); 41 | Object retVal = null; 42 | // 获取拦截器链 43 | List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); 44 | if (chain == null || chain.isEmpty()) { 45 | return method.invoke(target, args); 46 | } else { 47 | // 将拦截器统一封装成ReflectiveMethodInvocation 48 | MethodInvocation invocation = 49 | new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); 50 | // Proceed to the joinpoint through the interceptor chain. 51 | // 执行拦截器链 52 | retVal = invocation.proceed(); 53 | } 54 | return retVal; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/aop/framework/ProxyFactory.java: -------------------------------------------------------------------------------- 1 | package org.springframework.aop.framework; 2 | 3 | import org.springframework.aop.AdvisedSupport; 4 | 5 | /** 6 | * @author zqc 7 | * @date 2022/12/16 8 | */ 9 | public class ProxyFactory extends AdvisedSupport { 10 | 11 | 12 | public ProxyFactory() { 13 | } 14 | 15 | public Object getProxy() { 16 | return createAopProxy().getProxy(); 17 | } 18 | 19 | private AopProxy createAopProxy() { 20 | if (this.isProxyTargetClass() || this.getTargetSource().getTargetClass().length == 0) { 21 | return new CglibAopProxy(this); 22 | } 23 | 24 | return new JdkDynamicAopProxy(this); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/aop/framework/ReflectiveMethodInvocation.java: -------------------------------------------------------------------------------- 1 | package org.springframework.aop.framework; 2 | 3 | import org.aopalliance.intercept.MethodInterceptor; 4 | import org.aopalliance.intercept.MethodInvocation; 5 | 6 | import java.lang.reflect.AccessibleObject; 7 | import java.lang.reflect.Method; 8 | import java.util.List; 9 | 10 | /** 11 | * @author zqc 12 | * @date 2022/12/16 13 | */ 14 | public class ReflectiveMethodInvocation implements MethodInvocation { 15 | 16 | protected final Object proxy; 17 | 18 | protected final Object target; 19 | 20 | protected final Method method; 21 | 22 | protected final Object[] arguments; 23 | 24 | protected final Class targetClass; 25 | 26 | protected final List interceptorsAndDynamicMethodMatchers; 27 | 28 | private int currentInterceptorIndex = -1; 29 | 30 | public ReflectiveMethodInvocation(Object proxy,Object target, Method method, Object[] arguments,Class targetClass,List chain) { 31 | this.proxy=proxy; 32 | this.target = target; 33 | this.method = method; 34 | this.arguments = arguments; 35 | this.targetClass=targetClass; 36 | this.interceptorsAndDynamicMethodMatchers=chain; 37 | } 38 | 39 | @Override 40 | public Object proceed() throws Throwable { 41 | // 初始currentInterceptorIndex为-1,每调用一次proceed就把currentInterceptorIndex+1 42 | if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { 43 | // 当调用次数 = 拦截器个数时 44 | // 触发当前method方法 45 | return method.invoke(this.target, this.arguments); 46 | } 47 | 48 | Object interceptorOrInterceptionAdvice = 49 | this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); 50 | // 普通拦截器,直接触发拦截器invoke方法 51 | return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); 52 | } 53 | 54 | @Override 55 | public Method getMethod() { 56 | return method; 57 | } 58 | 59 | @Override 60 | public Object[] getArguments() { 61 | return arguments; 62 | } 63 | 64 | @Override 65 | public Object getThis() { 66 | return target; 67 | } 68 | 69 | @Override 70 | public AccessibleObject getStaticPart() { 71 | return method; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/aop/framework/adapter/AfterReturningAdviceInterceptor.java: -------------------------------------------------------------------------------- 1 | package org.springframework.aop.framework.adapter; 2 | 3 | import org.aopalliance.intercept.MethodInterceptor; 4 | import org.aopalliance.intercept.MethodInvocation; 5 | 6 | import org.springframework.aop.AfterAdvice; 7 | import org.springframework.aop.AfterReturningAdvice; 8 | 9 | /** 10 | * 后置增强拦截器 11 | * 12 | * @author zqc 13 | * @date 2022/12/20 14 | */ 15 | public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice { 16 | 17 | private AfterReturningAdvice advice; 18 | 19 | public AfterReturningAdviceInterceptor() { 20 | } 21 | 22 | public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) { 23 | this.advice = advice; 24 | } 25 | 26 | 27 | @Override 28 | public Object invoke(MethodInvocation mi) throws Throwable { 29 | Object retVal = mi.proceed(); 30 | this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis()); 31 | return retVal; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/aop/framework/adapter/MethodBeforeAdviceInterceptor.java: -------------------------------------------------------------------------------- 1 | package org.springframework.aop.framework.adapter; 2 | 3 | import org.aopalliance.intercept.MethodInterceptor; 4 | import org.aopalliance.intercept.MethodInvocation; 5 | import org.springframework.aop.BeforeAdvice; 6 | import org.springframework.aop.MethodBeforeAdvice; 7 | 8 | /** 9 | * @author derekyi 10 | * @date 2020/12/6 11 | */ 12 | public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice { 13 | 14 | private MethodBeforeAdvice advice; 15 | 16 | public MethodBeforeAdviceInterceptor() { 17 | } 18 | 19 | public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) { 20 | this.advice = advice; 21 | } 22 | 23 | public void setAdvice(MethodBeforeAdvice advice) { 24 | this.advice = advice; 25 | } 26 | 27 | @Override 28 | public Object invoke(MethodInvocation mi) throws Throwable { 29 | //在执行被代理方法之前,先执行before advice操作 30 | this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis()); 31 | return mi.proceed(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/aop/framework/autoproxy/DefaultAdvisorAutoProxyCreator.java: -------------------------------------------------------------------------------- 1 | package org.springframework.aop.framework.autoproxy; 2 | 3 | import java.util.Collection; 4 | import java.util.HashSet; 5 | import java.util.Set; 6 | 7 | import org.aopalliance.aop.Advice; 8 | 9 | import org.springframework.aop.Advisor; 10 | import org.springframework.aop.ClassFilter; 11 | import org.springframework.aop.Pointcut; 12 | import org.springframework.aop.TargetSource; 13 | import org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor; 14 | import org.springframework.aop.framework.ProxyFactory; 15 | import org.springframework.beans.BeansException; 16 | import org.springframework.beans.PropertyValues; 17 | import org.springframework.beans.factory.BeanFactory; 18 | import org.springframework.beans.factory.BeanFactoryAware; 19 | import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor; 20 | import org.springframework.beans.factory.support.DefaultListableBeanFactory; 21 | 22 | /** 23 | * @author derekyi 24 | * @date 2020/12/6 25 | */ 26 | public class DefaultAdvisorAutoProxyCreator implements InstantiationAwareBeanPostProcessor, BeanFactoryAware { 27 | 28 | private DefaultListableBeanFactory beanFactory; 29 | 30 | private Set earlyProxyReferences = new HashSet<>(); 31 | 32 | @Override 33 | public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 34 | if (!earlyProxyReferences.contains(beanName)) { 35 | return wrapIfNecessary(bean, beanName); 36 | } 37 | 38 | return bean; 39 | } 40 | 41 | @Override 42 | public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException { 43 | earlyProxyReferences.add(beanName); 44 | return wrapIfNecessary(bean, beanName); 45 | } 46 | 47 | protected Object wrapIfNecessary(Object bean, String beanName) { 48 | //避免死循环 49 | if (isInfrastructureClass(bean.getClass())) { 50 | return bean; 51 | } 52 | 53 | Collection advisors = beanFactory.getBeansOfType(AspectJExpressionPointcutAdvisor.class) 54 | .values(); 55 | try { 56 | ProxyFactory proxyFactory = new ProxyFactory(); 57 | for (AspectJExpressionPointcutAdvisor advisor : advisors) { 58 | ClassFilter classFilter = advisor.getPointcut().getClassFilter(); 59 | if (classFilter.matches(bean.getClass())) { 60 | TargetSource targetSource = new TargetSource(bean); 61 | proxyFactory.setTargetSource(targetSource); 62 | proxyFactory.addAdvisor(advisor); 63 | proxyFactory.setMethodMatcher(advisor.getPointcut().getMethodMatcher()); 64 | } 65 | } 66 | if (!proxyFactory.getAdvisors().isEmpty()) { 67 | return proxyFactory.getProxy(); 68 | } 69 | } catch (Exception ex) { 70 | throw new BeansException("Error create proxy bean for: " + beanName, ex); 71 | } 72 | return bean; 73 | } 74 | 75 | private boolean isInfrastructureClass(Class beanClass) { 76 | return Advice.class.isAssignableFrom(beanClass) 77 | || Pointcut.class.isAssignableFrom(beanClass) 78 | || Advisor.class.isAssignableFrom(beanClass); 79 | } 80 | 81 | @Override 82 | public void setBeanFactory(BeanFactory beanFactory) throws BeansException { 83 | this.beanFactory = (DefaultListableBeanFactory) beanFactory; 84 | } 85 | 86 | @Override 87 | public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException { 88 | return null; 89 | } 90 | 91 | @Override 92 | public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { 93 | return true; 94 | } 95 | 96 | @Override 97 | public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 98 | return bean; 99 | } 100 | 101 | @Override 102 | public PropertyValues postProcessPropertyValues(PropertyValues pvs, Object bean, String beanName) throws BeansException { 103 | return pvs; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/BeansException.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans; 2 | 3 | /** 4 | * @author derekyi 5 | * @date 2020/11/22 6 | */ 7 | public class BeansException extends RuntimeException { 8 | 9 | public BeansException(String msg) { 10 | super(msg); 11 | } 12 | 13 | public BeansException(String msg, Throwable cause) { 14 | super(msg, cause); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/PropertyValue.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans; 2 | 3 | /** 4 | * bean属性信息 5 | * 6 | * @author derekyi 7 | * @date 2020/11/23 8 | */ 9 | public class PropertyValue { 10 | 11 | private final String name; 12 | 13 | private final Object value; 14 | 15 | public PropertyValue(String name, Object value) { 16 | this.name = name; 17 | this.value = value; 18 | } 19 | 20 | public String getName() { 21 | return name; 22 | } 23 | 24 | public Object getValue() { 25 | return value; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/PropertyValues.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @author derekyi 8 | * @date 2020/11/23 9 | */ 10 | public class PropertyValues { 11 | 12 | private final List propertyValueList = new ArrayList<>(); 13 | 14 | public void addPropertyValue(PropertyValue pv) { 15 | for (int i = 0; i < this.propertyValueList.size(); i++) { 16 | PropertyValue currentPv = this.propertyValueList.get(i); 17 | if (currentPv.getName().equals(pv.getName())) { 18 | //覆盖原有的属性值 19 | this.propertyValueList.set(i, pv); 20 | return; 21 | } 22 | } 23 | this.propertyValueList.add(pv); 24 | } 25 | 26 | public PropertyValue[] getPropertyValues() { 27 | return this.propertyValueList.toArray(new PropertyValue[0]); 28 | } 29 | 30 | public PropertyValue getPropertyValue(String propertyName) { 31 | for (int i = 0; i < this.propertyValueList.size(); i++) { 32 | PropertyValue pv = this.propertyValueList.get(i); 33 | if (pv.getName().equals(propertyName)) { 34 | return pv; 35 | } 36 | } 37 | return null; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/Aware.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory; 2 | 3 | /** 4 | * 标记类接口,实现该接口能感知容器类接口 5 | * 6 | * @author derekyi 7 | * @date 2020/12/1 8 | */ 9 | public interface Aware { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/BeanFactory.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory; 2 | 3 | import org.springframework.beans.BeansException; 4 | 5 | /** 6 | * bean容器 7 | * 8 | * @author derekyi 9 | * @date 2020/11/22 10 | */ 11 | public interface BeanFactory { 12 | 13 | /** 14 | * 获取bean 15 | * 16 | * @param name 17 | * @return 18 | * @throws BeansException bean不存在时 19 | */ 20 | Object getBean(String name) throws BeansException; 21 | 22 | /** 23 | * 根据名称和类型查找bean 24 | * 25 | * @param name 26 | * @param requiredType 27 | * @param 28 | * @return 29 | * @throws BeansException 30 | */ 31 | T getBean(String name, Class requiredType) throws BeansException; 32 | 33 | T getBean(Class requiredType) throws BeansException; 34 | 35 | boolean containsBean(String name); 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/BeanFactoryAware.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory; 2 | 3 | import org.springframework.beans.BeansException; 4 | 5 | /** 6 | * 实现该接口,能感知所属BeanFactory 7 | * 8 | * @author derekyi 9 | * @date 2020/12/1 10 | */ 11 | public interface BeanFactoryAware extends Aware { 12 | 13 | void setBeanFactory(BeanFactory beanFactory) throws BeansException; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/ConfigurableListableBeanFactory.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.factory.config.AutowireCapableBeanFactory; 5 | import org.springframework.beans.factory.config.BeanDefinition; 6 | import org.springframework.beans.factory.config.BeanPostProcessor; 7 | import org.springframework.beans.factory.config.ConfigurableBeanFactory; 8 | import org.springframework.beans.factory.support.AbstractBeanFactory; 9 | 10 | /** 11 | * @author derekyi 12 | * @date 2020/11/28 13 | */ 14 | public interface ConfigurableListableBeanFactory extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory { 15 | 16 | /** 17 | * 根据名称查找BeanDefinition 18 | * 19 | * @param beanName 20 | * @return 21 | * @throws BeansException 如果找不到BeanDefintion 22 | */ 23 | BeanDefinition getBeanDefinition(String beanName) throws BeansException; 24 | 25 | /** 26 | * 提前实例化所有单例实例 27 | * 28 | * @throws BeansException 29 | */ 30 | void preInstantiateSingletons() throws BeansException; 31 | 32 | void addBeanPostProcessor(BeanPostProcessor beanPostProcessor); 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/DisposableBean.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory; 2 | 3 | /** 4 | * @author derekyi 5 | * @date 2020/11/29 6 | */ 7 | public interface DisposableBean { 8 | 9 | void destroy() throws Exception; 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/FactoryBean.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory; 2 | 3 | /** 4 | * @author derekyi 5 | * @date 2020/12/2 6 | */ 7 | public interface FactoryBean { 8 | 9 | T getObject() throws Exception; 10 | 11 | boolean isSingleton(); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/HierarchicalBeanFactory.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory; 2 | 3 | /** 4 | * @author derekyi 5 | * @date 2020/11/28 6 | */ 7 | public interface HierarchicalBeanFactory extends BeanFactory { 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/InitializingBean.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory; 2 | 3 | /** 4 | * @author derekyi 5 | * @date 2020/11/29 6 | */ 7 | public interface InitializingBean { 8 | 9 | void afterPropertiesSet() throws Exception; 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/ListableBeanFactory.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory; 2 | 3 | import org.springframework.beans.BeansException; 4 | 5 | import java.util.Map; 6 | 7 | /** 8 | * @author derekyi 9 | * @date 2020/11/28 10 | */ 11 | public interface ListableBeanFactory extends BeanFactory { 12 | 13 | /** 14 | * 返回指定类型的所有实例 15 | * 16 | * @param type 17 | * @param 18 | * @return 19 | * @throws BeansException 20 | */ 21 | Map getBeansOfType(Class type) throws BeansException; 22 | 23 | /** 24 | * 返回定义的所有bean的名称 25 | * 26 | * @return 27 | */ 28 | String[] getBeanDefinitionNames(); 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/ObjectFactory.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory; 2 | 3 | import org.springframework.beans.BeansException; 4 | 5 | /** 6 | * @author derekyi 7 | * @date 2021/1/30 8 | */ 9 | public interface ObjectFactory { 10 | 11 | T getObject() throws BeansException; 12 | } -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/PropertyPlaceholderConfigurer.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.PropertyValue; 5 | import org.springframework.beans.PropertyValues; 6 | import org.springframework.beans.factory.config.BeanDefinition; 7 | import org.springframework.beans.factory.config.BeanFactoryPostProcessor; 8 | import org.springframework.core.io.DefaultResourceLoader; 9 | import org.springframework.core.io.Resource; 10 | import org.springframework.util.StringValueResolver; 11 | 12 | import java.io.IOException; 13 | import java.util.Properties; 14 | 15 | /** 16 | * @author derekyi 17 | * @date 2020/12/13 18 | */ 19 | public class PropertyPlaceholderConfigurer implements BeanFactoryPostProcessor { 20 | 21 | public static final String PLACEHOLDER_PREFIX = "${"; 22 | 23 | public static final String PLACEHOLDER_SUFFIX = "}"; 24 | 25 | private String location; 26 | 27 | @Override 28 | public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { 29 | //加载属性配置文件 30 | Properties properties = loadProperties(); 31 | 32 | //属性值替换占位符 33 | processProperties(beanFactory, properties); 34 | 35 | //往容器中添加字符解析器,供解析@Value注解使用 36 | StringValueResolver valueResolver = new PlaceholderResolvingStringValueResolver(properties); 37 | beanFactory.addEmbeddedValueResolver(valueResolver); 38 | } 39 | 40 | /** 41 | * 加载属性配置文件 42 | * 43 | * @return 44 | */ 45 | private Properties loadProperties() { 46 | try { 47 | DefaultResourceLoader resourceLoader = new DefaultResourceLoader(); 48 | Resource resource = resourceLoader.getResource(location); 49 | Properties properties = new Properties(); 50 | properties.load(resource.getInputStream()); 51 | return properties; 52 | } catch (IOException e) { 53 | throw new BeansException("Could not load properties", e); 54 | } 55 | } 56 | 57 | /** 58 | * 属性值替换占位符 59 | * 60 | * @param beanFactory 61 | * @param properties 62 | * @throws BeansException 63 | */ 64 | private void processProperties(ConfigurableListableBeanFactory beanFactory, Properties properties) throws BeansException { 65 | String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames(); 66 | for (String beanName : beanDefinitionNames) { 67 | BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName); 68 | resolvePropertyValues(beanDefinition, properties); 69 | } 70 | } 71 | 72 | private void resolvePropertyValues(BeanDefinition beanDefinition, Properties properties) { 73 | PropertyValues propertyValues = beanDefinition.getPropertyValues(); 74 | for (PropertyValue propertyValue : propertyValues.getPropertyValues()) { 75 | Object value = propertyValue.getValue(); 76 | if (value instanceof String) { 77 | value = resolvePlaceholder((String) value, properties); 78 | propertyValues.addPropertyValue(new PropertyValue(propertyValue.getName(), value)); 79 | } 80 | } 81 | } 82 | 83 | private String resolvePlaceholder(String value, Properties properties) { 84 | //TODO 仅简单支持一个占位符的格式 85 | String strVal = value; 86 | StringBuffer buf = new StringBuffer(strVal); 87 | int startIndex = strVal.indexOf(PLACEHOLDER_PREFIX); 88 | int endIndex = strVal.indexOf(PLACEHOLDER_SUFFIX); 89 | if (startIndex != -1 && endIndex != -1 && startIndex < endIndex) { 90 | String propKey = strVal.substring(startIndex + 2, endIndex); 91 | String propVal = properties.getProperty(propKey); 92 | buf.replace(startIndex, endIndex + 1, propVal); 93 | } 94 | return buf.toString(); 95 | } 96 | 97 | public void setLocation(String location) { 98 | this.location = location; 99 | } 100 | 101 | private class PlaceholderResolvingStringValueResolver implements StringValueResolver { 102 | 103 | private final Properties properties; 104 | 105 | public PlaceholderResolvingStringValueResolver(Properties properties) { 106 | this.properties = properties; 107 | } 108 | 109 | public String resolveStringValue(String strVal) throws BeansException { 110 | return PropertyPlaceholderConfigurer.this.resolvePlaceholder(strVal, properties); 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/annotation/Autowired.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author derekyi 10 | * @date 2020/12/27 11 | */ 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD}) 14 | public @interface Autowired { 15 | 16 | } -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory.annotation; 2 | 3 | import cn.hutool.core.bean.BeanUtil; 4 | import cn.hutool.core.util.TypeUtil; 5 | import org.springframework.beans.BeansException; 6 | import org.springframework.beans.PropertyValues; 7 | import org.springframework.beans.factory.BeanFactory; 8 | import org.springframework.beans.factory.BeanFactoryAware; 9 | import org.springframework.beans.factory.ConfigurableListableBeanFactory; 10 | import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor; 11 | import org.springframework.core.convert.ConversionService; 12 | 13 | import java.lang.reflect.Field; 14 | 15 | /** 16 | * 处理@Autowired和@Value注解的BeanPostProcessor 17 | * 18 | * @author derekyi 19 | * @date 2020/12/27 20 | */ 21 | public class AutowiredAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor, BeanFactoryAware { 22 | 23 | private ConfigurableListableBeanFactory beanFactory; 24 | 25 | @Override 26 | public void setBeanFactory(BeanFactory beanFactory) throws BeansException { 27 | this.beanFactory = (ConfigurableListableBeanFactory) beanFactory; 28 | } 29 | 30 | @Override 31 | public PropertyValues postProcessPropertyValues(PropertyValues pvs, Object bean, String beanName) throws BeansException { 32 | //处理@Value注解 33 | Class clazz = bean.getClass(); 34 | Field[] fields = clazz.getDeclaredFields(); 35 | for (Field field : fields) { 36 | Value valueAnnotation = field.getAnnotation(Value.class); 37 | if (valueAnnotation != null) { 38 | Object value = valueAnnotation.value(); 39 | value = beanFactory.resolveEmbeddedValue((String) value); 40 | 41 | //类型转换 42 | Class sourceType = value.getClass(); 43 | Class targetType = (Class) TypeUtil.getType(field); 44 | ConversionService conversionService = beanFactory.getConversionService(); 45 | if (conversionService != null) { 46 | if (conversionService.canConvert(sourceType, targetType)) { 47 | value = conversionService.convert(value, targetType); 48 | } 49 | } 50 | 51 | BeanUtil.setFieldValue(bean, field.getName(), value); 52 | } 53 | } 54 | 55 | //处理@Autowired注解 56 | for (Field field : fields) { 57 | Autowired autowiredAnnotation = field.getAnnotation(Autowired.class); 58 | if (autowiredAnnotation != null) { 59 | Class fieldType = field.getType(); 60 | String dependentBeanName = null; 61 | Qualifier qualifierAnnotation = field.getAnnotation(Qualifier.class); 62 | Object dependentBean = null; 63 | if (qualifierAnnotation != null) { 64 | dependentBeanName = qualifierAnnotation.value(); 65 | dependentBean = beanFactory.getBean(dependentBeanName, fieldType); 66 | } else { 67 | dependentBean = beanFactory.getBean(fieldType); 68 | } 69 | BeanUtil.setFieldValue(bean, field.getName(), dependentBean); 70 | } 71 | } 72 | 73 | return pvs; 74 | } 75 | 76 | @Override 77 | public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException { 78 | return null; 79 | } 80 | 81 | @Override 82 | public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { 83 | return true; 84 | } 85 | 86 | @Override 87 | public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 88 | return null; 89 | } 90 | 91 | @Override 92 | public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 93 | return null; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/annotation/Qualifier.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @author derekyi 7 | * @date 2020/12/27 8 | */ 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE}) 11 | @Inherited 12 | @Documented 13 | public @interface Qualifier { 14 | 15 | String value() default ""; 16 | 17 | } -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/annotation/Value.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author derekyi 10 | * @date 2020/12/27 11 | */ 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) 14 | public @interface Value { 15 | 16 | String value(); 17 | } -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/config/AutowireCapableBeanFactory.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory.config; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.factory.BeanFactory; 5 | 6 | /** 7 | * @author derekyi 8 | * @date 2020/11/28 9 | */ 10 | public interface AutowireCapableBeanFactory extends BeanFactory { 11 | 12 | /** 13 | * 执行BeanPostProcessors的postProcessBeforeInitialization方法 14 | * 15 | * @param existingBean 16 | * @param beanName 17 | * @return 18 | * @throws BeansException 19 | */ 20 | Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) 21 | throws BeansException; 22 | 23 | /** 24 | * 执行BeanPostProcessors的postProcessAfterInitialization方法 25 | * 26 | * @param existingBean 27 | * @param beanName 28 | * @return 29 | * @throws BeansException 30 | */ 31 | Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) 32 | throws BeansException; 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/config/BeanDefinition.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory.config; 2 | 3 | import org.springframework.beans.PropertyValues; 4 | 5 | import java.util.Objects; 6 | 7 | /** 8 | * BeanDefinition实例保存bean的信息,包括class类型、方法构造参数、bean属性、bean的scope等,此处简化只包含class类型和bean属性 9 | * 10 | * @author derekyi 11 | * @date 2020/11/22 12 | */ 13 | public class BeanDefinition { 14 | 15 | public static String SCOPE_SINGLETON = "singleton"; 16 | 17 | public static String SCOPE_PROTOTYPE = "prototype"; 18 | 19 | 20 | /** 21 | * bean class类 22 | */ 23 | private Class beanClass; 24 | 25 | /** 26 | * class 属性值 27 | */ 28 | private PropertyValues propertyValues; 29 | /** 30 | * 通过反射 初始化方法名称 31 | */ 32 | private String initMethodName; 33 | /** 34 | * 销毁方法名称 35 | */ 36 | private String destroyMethodName; 37 | /** 38 | * 作用域 默认单例Bean 39 | */ 40 | private String scope = SCOPE_SINGLETON; 41 | 42 | private boolean singleton = true; 43 | 44 | private boolean prototype = false; 45 | 46 | /*/* 47 | 懒加载 48 | */ 49 | private boolean lazyInit=false; 50 | 51 | public BeanDefinition(Class beanClass) { 52 | this(beanClass, null); 53 | } 54 | 55 | public BeanDefinition(Class beanClass, PropertyValues propertyValues) { 56 | this.beanClass = beanClass; 57 | this.propertyValues = propertyValues != null ? propertyValues : new PropertyValues(); 58 | } 59 | 60 | public void setScope(String scope) { 61 | this.scope = scope; 62 | this.singleton = SCOPE_SINGLETON.equals(scope); 63 | this.prototype = SCOPE_PROTOTYPE.equals(scope); 64 | } 65 | 66 | public boolean isSingleton() { 67 | return this.singleton; 68 | } 69 | 70 | public boolean isPrototype() { 71 | return this.prototype; 72 | } 73 | 74 | public Class getBeanClass() { 75 | return beanClass; 76 | } 77 | 78 | public void setBeanClass(Class beanClass) { 79 | this.beanClass = beanClass; 80 | } 81 | 82 | public PropertyValues getPropertyValues() { 83 | return propertyValues; 84 | } 85 | 86 | public void setPropertyValues(PropertyValues propertyValues) { 87 | this.propertyValues = propertyValues; 88 | } 89 | 90 | public String getInitMethodName() { 91 | return initMethodName; 92 | } 93 | 94 | public void setInitMethodName(String initMethodName) { 95 | this.initMethodName = initMethodName; 96 | } 97 | 98 | public String getDestroyMethodName() { 99 | return destroyMethodName; 100 | } 101 | 102 | public void setDestroyMethodName(String destroyMethodName) { 103 | this.destroyMethodName = destroyMethodName; 104 | } 105 | 106 | @Override 107 | public boolean equals(Object o) { 108 | if (this == o) return true; 109 | if (o == null || getClass() != o.getClass()) return false; 110 | BeanDefinition that = (BeanDefinition) o; 111 | return beanClass.equals(that.beanClass); 112 | } 113 | 114 | @Override 115 | public int hashCode() { 116 | return Objects.hash(beanClass); 117 | } 118 | 119 | public void setLazyInit(boolean b){ 120 | lazyInit=b; 121 | } 122 | 123 | public boolean isLazyInit(){ 124 | return lazyInit; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/config/BeanFactoryPostProcessor.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory.config; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.factory.ConfigurableListableBeanFactory; 5 | 6 | /** 7 | * 允许自定义修改BeanDefinition的属性值 8 | * 9 | * @author derekyi 10 | * @date 2020/11/28 11 | */ 12 | public interface BeanFactoryPostProcessor { 13 | 14 | /** 15 | * 在所有BeanDefintion加载完成后,但在bean实例化之前,提供修改BeanDefinition属性值的机制 16 | * 17 | * @param beanFactory 18 | * @throws BeansException 19 | */ 20 | void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/config/BeanPostProcessor.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory.config; 2 | 3 | import org.springframework.beans.BeansException; 4 | 5 | /** 6 | * 用于修改实例化后的bean的修改扩展点 7 | * 8 | * @author derekyi 9 | * @date 2020/11/28 10 | */ 11 | public interface BeanPostProcessor { 12 | 13 | /** 14 | * 在bean执行初始化方法之前执行此方法 15 | * 16 | * @param bean 17 | * @param beanName 18 | * @return 19 | * @throws BeansException 20 | */ 21 | Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException; 22 | 23 | /** 24 | * 在bean执行初始化方法之后执行此方法 25 | * 26 | * @param bean 27 | * @param beanName 28 | * @return 29 | * @throws BeansException 30 | */ 31 | Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException; 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/config/BeanReference.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory.config; 2 | 3 | /** 4 | * 一个bean对另一个bean的引用 5 | * 6 | * @author derekyi 7 | * @date 2020/11/24 8 | */ 9 | public class BeanReference { 10 | 11 | private final String beanName; 12 | 13 | 14 | public BeanReference(String beanName) { 15 | this.beanName = beanName; 16 | } 17 | 18 | public String getBeanName() { 19 | return beanName; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/config/ConfigurableBeanFactory.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory.config; 2 | 3 | import org.springframework.beans.factory.HierarchicalBeanFactory; 4 | import org.springframework.core.convert.ConversionService; 5 | import org.springframework.util.StringValueResolver; 6 | 7 | /** 8 | * @author derekyi 9 | * @date 2020/11/28 10 | */ 11 | public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry { 12 | 13 | /** 14 | * @param beanPostProcessor 15 | */ 16 | void addBeanPostProcessor(BeanPostProcessor beanPostProcessor); 17 | 18 | /** 19 | * 销毁单例bean 20 | */ 21 | void destroySingletons(); 22 | 23 | void addEmbeddedValueResolver(StringValueResolver valueResolver); 24 | 25 | String resolveEmbeddedValue(String value); 26 | 27 | void setConversionService(ConversionService conversionService); 28 | 29 | ConversionService getConversionService(); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/config/InstantiationAwareBeanPostProcessor.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory.config; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.PropertyValues; 5 | 6 | /** 7 | * @author derekyi 8 | * @date 2020/12/6 9 | */ 10 | public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor { 11 | 12 | /** 13 | * 在bean实例化之前执行 14 | * 15 | * @param beanClass 16 | * @param beanName 17 | * @return 18 | * @throws BeansException 19 | */ 20 | Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException; 21 | 22 | /** 23 | * bean实例化之后,设置属性之前执行 24 | * 25 | * @param bean 26 | * @param beanName 27 | * @return 28 | * @throws BeansException 29 | */ 30 | boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException; 31 | 32 | /** 33 | * bean实例化之后,设置属性之前执行 34 | * 35 | * @param pvs 36 | * @param bean 37 | * @param beanName 38 | * @return 39 | * @throws BeansException 40 | */ 41 | PropertyValues postProcessPropertyValues(PropertyValues pvs, Object bean, String beanName) 42 | throws BeansException; 43 | 44 | /** 45 | * 提前暴露bean 46 | * 47 | * @param bean 48 | * @param beanName 49 | * @return 50 | * @throws BeansException 51 | */ 52 | default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException { 53 | return bean; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/config/SingletonBeanRegistry.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory.config; 2 | 3 | /** 4 | * 单例注册表 5 | * 6 | * @author derekyi 7 | * @date 2020/11/22 8 | */ 9 | public interface SingletonBeanRegistry { 10 | 11 | Object getSingleton(String beanName); 12 | 13 | void addSingleton(String beanName, Object singletonObject); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/support/AbstractBeanDefinitionReader.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory.support; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.core.io.DefaultResourceLoader; 5 | import org.springframework.core.io.Resource; 6 | import org.springframework.core.io.ResourceLoader; 7 | 8 | /** 9 | * @author derekyi 10 | * @date 2020/11/26 11 | */ 12 | public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader { 13 | 14 | private final BeanDefinitionRegistry registry; 15 | 16 | private ResourceLoader resourceLoader; 17 | 18 | protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) { 19 | this(registry, new DefaultResourceLoader()); 20 | } 21 | 22 | public AbstractBeanDefinitionReader(BeanDefinitionRegistry registry, ResourceLoader resourceLoader) { 23 | this.registry = registry; 24 | this.resourceLoader = resourceLoader; 25 | } 26 | 27 | @Override 28 | public BeanDefinitionRegistry getRegistry() { 29 | return registry; 30 | } 31 | 32 | @Override 33 | public void loadBeanDefinitions(String[] locations) throws BeansException { 34 | for (String location : locations) { 35 | loadBeanDefinitions(location); 36 | } 37 | } 38 | 39 | public void setResourceLoader(ResourceLoader resourceLoader) { 40 | this.resourceLoader = resourceLoader; 41 | } 42 | 43 | @Override 44 | public ResourceLoader getResourceLoader() { 45 | return resourceLoader; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory.support; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.factory.FactoryBean; 5 | import org.springframework.beans.factory.config.BeanDefinition; 6 | import org.springframework.beans.factory.config.BeanPostProcessor; 7 | import org.springframework.beans.factory.config.ConfigurableBeanFactory; 8 | import org.springframework.core.convert.ConversionService; 9 | import org.springframework.util.StringValueResolver; 10 | 11 | import java.util.ArrayList; 12 | import java.util.HashMap; 13 | import java.util.List; 14 | import java.util.Map; 15 | 16 | /** 17 | * @author derekyi 18 | * @date 2020/11/22 19 | */ 20 | public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements ConfigurableBeanFactory { 21 | 22 | private final List beanPostProcessors = new ArrayList<>(); 23 | 24 | private final Map factoryBeanObjectCache = new HashMap<>(); 25 | 26 | private final List embeddedValueResolvers = new ArrayList(); 27 | 28 | private ConversionService conversionService; 29 | 30 | 31 | @Override 32 | public Object getBean(String name) throws BeansException { 33 | Object sharedInstance = getSingleton(name); 34 | if (sharedInstance != null) { 35 | //如果是FactoryBean,从FactoryBean#getObject中创建bean 36 | return getObjectForBeanInstance(sharedInstance, name); 37 | } 38 | 39 | BeanDefinition beanDefinition = getBeanDefinition(name); 40 | Object bean = createBean(name, beanDefinition); 41 | return getObjectForBeanInstance(bean, name); 42 | } 43 | 44 | /** 45 | * 如果是FactoryBean,从FactoryBean#getObject中创建bean 46 | * 47 | * @param beanInstance 48 | * @param beanName 49 | * @return 50 | */ 51 | protected Object getObjectForBeanInstance(Object beanInstance, String beanName) { 52 | Object object = beanInstance; 53 | if (beanInstance instanceof FactoryBean) { 54 | FactoryBean factoryBean = (FactoryBean) beanInstance; 55 | try { 56 | if (factoryBean.isSingleton()) { 57 | //singleton作用域bean,从缓存中获取 58 | object = this.factoryBeanObjectCache.get(beanName); 59 | if (object == null) { 60 | object = factoryBean.getObject(); 61 | this.factoryBeanObjectCache.put(beanName, object); 62 | } 63 | } else { 64 | //prototype作用域bean,新创建bean 65 | object = factoryBean.getObject(); 66 | } 67 | } catch (Exception ex) { 68 | throw new BeansException("FactoryBean threw exception on object[" + beanName + "] creation", ex); 69 | } 70 | } 71 | 72 | return object; 73 | } 74 | 75 | @Override 76 | public T getBean(String name, Class requiredType) throws BeansException { 77 | return ((T) getBean(name)); 78 | } 79 | 80 | @Override 81 | public boolean containsBean(String name) { 82 | return containsBeanDefinition(name); 83 | } 84 | 85 | protected abstract boolean containsBeanDefinition(String beanName); 86 | 87 | protected abstract Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException; 88 | 89 | protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException; 90 | 91 | @Override 92 | public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) { 93 | //有则覆盖 94 | this.beanPostProcessors.remove(beanPostProcessor); 95 | this.beanPostProcessors.add(beanPostProcessor); 96 | } 97 | 98 | public List getBeanPostProcessors() { 99 | return this.beanPostProcessors; 100 | } 101 | 102 | public void addEmbeddedValueResolver(StringValueResolver valueResolver) { 103 | this.embeddedValueResolvers.add(valueResolver); 104 | } 105 | 106 | public String resolveEmbeddedValue(String value) { 107 | String result = value; 108 | for (StringValueResolver resolver : this.embeddedValueResolvers) { 109 | result = resolver.resolveStringValue(result); 110 | } 111 | return result; 112 | } 113 | 114 | @Override 115 | public ConversionService getConversionService() { 116 | return conversionService; 117 | } 118 | 119 | @Override 120 | public void setConversionService(ConversionService conversionService) { 121 | this.conversionService = conversionService; 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/support/BeanDefinitionReader.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory.support; 2 | 3 | import cn.hutool.core.bean.BeanException; 4 | import org.springframework.beans.BeansException; 5 | import org.springframework.core.io.Resource; 6 | import org.springframework.core.io.ResourceLoader; 7 | 8 | /** 9 | * 读取bean定义信息即BeanDefinition的接口 10 | * 11 | * @author derekyi 12 | * @date 2020/11/26 13 | */ 14 | public interface BeanDefinitionReader { 15 | 16 | BeanDefinitionRegistry getRegistry(); 17 | 18 | ResourceLoader getResourceLoader(); 19 | 20 | void loadBeanDefinitions(Resource resource) throws BeansException; 21 | 22 | void loadBeanDefinitions(String location) throws BeansException; 23 | 24 | void loadBeanDefinitions(String[] locations) throws BeansException; 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/support/BeanDefinitionRegistry.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory.support; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.factory.config.BeanDefinition; 5 | 6 | /** 7 | * BeanDefinition注册表接口 8 | * 9 | * @author derekyi 10 | * @date 2020/11/22 11 | */ 12 | public interface BeanDefinitionRegistry { 13 | 14 | /** 15 | * 向注册表中注BeanDefinition 16 | * 17 | * @param beanName 18 | * @param beanDefinition 19 | */ 20 | void registerBeanDefinition(String beanName, BeanDefinition beanDefinition); 21 | 22 | /** 23 | * 根据名称查找BeanDefinition 24 | * 25 | * @param beanName 26 | * @return 27 | * @throws BeansException 如果找不到BeanDefintion 28 | */ 29 | BeanDefinition getBeanDefinition(String beanName) throws BeansException; 30 | 31 | /** 32 | * 是否包含指定名称的BeanDefinition 33 | * 34 | * @param beanName 35 | * @return 36 | */ 37 | boolean containsBeanDefinition(String beanName); 38 | 39 | /** 40 | * 返回定义的所有bean的名称 41 | * 42 | * @return 43 | */ 44 | String[] getBeanDefinitionNames(); 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/support/CglibSubclassingInstantiationStrategy.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory.support; 2 | 3 | import net.sf.cglib.proxy.Enhancer; 4 | import net.sf.cglib.proxy.MethodInterceptor; 5 | import org.springframework.beans.BeansException; 6 | import org.springframework.beans.factory.config.BeanDefinition; 7 | 8 | /** 9 | * @author derekyi 10 | * @date 2020/11/23 11 | */ 12 | public class CglibSubclassingInstantiationStrategy implements InstantiationStrategy { 13 | 14 | /** 15 | * 使用CGLIB动态生成子类 16 | * 17 | * @param beanDefinition 18 | * @return 19 | * @throws BeansException 20 | */ 21 | @Override 22 | public Object instantiate(BeanDefinition beanDefinition) throws BeansException { 23 | Enhancer enhancer = new Enhancer(); 24 | enhancer.setSuperclass(beanDefinition.getBeanClass()); 25 | enhancer.setCallback((MethodInterceptor) (obj, method, argsTemp, proxy) -> proxy.invokeSuper(obj,argsTemp)); 26 | return enhancer.create(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory.support; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.factory.ConfigurableListableBeanFactory; 5 | import org.springframework.beans.factory.config.BeanDefinition; 6 | 7 | import java.util.*; 8 | import java.util.concurrent.ConcurrentHashMap; 9 | 10 | /** 11 | * @author derekyi 12 | * @date 2020/11/22 13 | */ 14 | public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory 15 | implements ConfigurableListableBeanFactory, BeanDefinitionRegistry { 16 | 17 | private Map beanDefinitionMap = new ConcurrentHashMap<>(256); 18 | 19 | @Override 20 | public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) { 21 | beanDefinitionMap.put(beanName, beanDefinition); 22 | } 23 | 24 | @Override 25 | public BeanDefinition getBeanDefinition(String beanName) throws BeansException { 26 | BeanDefinition beanDefinition = beanDefinitionMap.get(beanName); 27 | if (beanDefinition == null) { 28 | throw new BeansException("No bean named '" + beanName + "' is defined"); 29 | } 30 | 31 | return beanDefinition; 32 | } 33 | 34 | @Override 35 | public boolean containsBeanDefinition(String beanName) { 36 | return beanDefinitionMap.containsKey(beanName); 37 | } 38 | 39 | @Override 40 | public Map getBeansOfType(Class type) throws BeansException { 41 | Map result = new HashMap<>(); 42 | beanDefinitionMap.forEach((beanName, beanDefinition) -> { 43 | Class beanClass = beanDefinition.getBeanClass(); 44 | if (type.isAssignableFrom(beanClass)) { 45 | T bean = (T) getBean(beanName); 46 | result.put(beanName, bean); 47 | } 48 | }); 49 | return result; 50 | } 51 | 52 | public T getBean(Class requiredType) throws BeansException { 53 | List beanNames = new ArrayList<>(); 54 | for (Map.Entry entry : beanDefinitionMap.entrySet()) { 55 | Class beanClass = entry.getValue().getBeanClass(); 56 | if (requiredType.isAssignableFrom(beanClass)) { 57 | beanNames.add(entry.getKey()); 58 | } 59 | } 60 | if (beanNames.size() == 1) { 61 | return getBean(beanNames.get(0), requiredType); 62 | } 63 | 64 | throw new BeansException(requiredType + "expected single bean but found " + 65 | beanNames.size() + ": " + beanNames); 66 | } 67 | 68 | @Override 69 | public String[] getBeanDefinitionNames() { 70 | Set beanNames = beanDefinitionMap.keySet(); 71 | return beanNames.toArray(new String[beanNames.size()]); 72 | } 73 | 74 | @Override 75 | public void preInstantiateSingletons() throws BeansException { 76 | beanDefinitionMap.forEach((beanName, beanDefinition) -> { 77 | //只有当bean是单例且不为懒加载才会被创建 78 | if (beanDefinition.isSingleton() && !beanDefinition.isLazyInit()) { 79 | getBean(beanName); 80 | } 81 | }); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory.support; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | import org.springframework.beans.BeansException; 8 | import org.springframework.beans.factory.DisposableBean; 9 | import org.springframework.beans.factory.ObjectFactory; 10 | import org.springframework.beans.factory.config.SingletonBeanRegistry; 11 | 12 | /** 13 | * @author derekyi 14 | * @date 2020/11/22 15 | */ 16 | public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry { 17 | 18 | /** 19 | * 一级缓存 20 | */ 21 | private Map singletonObjects = new HashMap<>(); 22 | 23 | /** 24 | * 二级缓存 25 | */ 26 | private Map earlySingletonObjects = new HashMap<>(); 27 | 28 | /** 29 | * 三级缓存 30 | */ 31 | private Map> singletonFactories = new HashMap>(); 32 | 33 | private final Map disposableBeans = new HashMap<>(); 34 | 35 | @Override 36 | public Object getSingleton(String beanName) { 37 | Object singletonObject = singletonObjects.get(beanName); 38 | if (singletonObject == null) { 39 | singletonObject = earlySingletonObjects.get(beanName); 40 | if (singletonObject == null) { 41 | ObjectFactory singletonFactory = singletonFactories.get(beanName); 42 | if (singletonFactory != null) { 43 | singletonObject = singletonFactory.getObject(); 44 | //从三级缓存放进二级缓存 45 | earlySingletonObjects.put(beanName, singletonObject); 46 | singletonFactories.remove(beanName); 47 | } 48 | } 49 | } 50 | return singletonObject; 51 | } 52 | 53 | @Override 54 | public void addSingleton(String beanName, Object singletonObject) { 55 | singletonObjects.put(beanName, singletonObject); // 1 56 | earlySingletonObjects.remove(beanName); // 2 57 | singletonFactories.remove(beanName); // 3 58 | } 59 | 60 | protected void addSingletonFactory(String beanName, ObjectFactory singletonFactory) { 61 | singletonFactories.put(beanName, singletonFactory); 62 | } 63 | 64 | public void registerDisposableBean(String beanName, DisposableBean bean) { 65 | disposableBeans.put(beanName, bean); 66 | } 67 | 68 | public void destroySingletons() { 69 | ArrayList beanNames = new ArrayList<>(disposableBeans.keySet()); 70 | for (String beanName : beanNames) { 71 | DisposableBean disposableBean = disposableBeans.remove(beanName); 72 | try { 73 | disposableBean.destroy(); 74 | } catch (Exception e) { 75 | throw new BeansException("Destroy method on bean with name '" + beanName + "' threw an exception", e); 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory.support; 2 | 3 | import cn.hutool.core.util.ClassUtil; 4 | import cn.hutool.core.util.StrUtil; 5 | import org.springframework.beans.BeansException; 6 | import org.springframework.beans.factory.DisposableBean; 7 | import org.springframework.beans.factory.config.BeanDefinition; 8 | 9 | import java.lang.reflect.Method; 10 | 11 | /** 12 | * @author derekyi 13 | * @date 2020/11/29 14 | */ 15 | public class DisposableBeanAdapter implements DisposableBean { 16 | 17 | private final Object bean; 18 | 19 | private final String beanName; 20 | 21 | private final String destroyMethodName; 22 | 23 | public DisposableBeanAdapter(Object bean, String beanName, BeanDefinition beanDefinition) { 24 | this.bean = bean; 25 | this.beanName = beanName; 26 | this.destroyMethodName = beanDefinition.getDestroyMethodName(); 27 | } 28 | 29 | @Override 30 | public void destroy() throws Exception { 31 | if (bean instanceof DisposableBean) { 32 | ((DisposableBean) bean).destroy(); 33 | } 34 | 35 | //避免同时继承自DisposableBean,且自定义方法与DisposableBean方法同名,销毁方法执行两次的情况 36 | if (StrUtil.isNotEmpty(destroyMethodName) && !(bean instanceof DisposableBean && "destroy".equals(this.destroyMethodName))) { 37 | //执行自定义方法 38 | Method destroyMethod = ClassUtil.getPublicMethod(bean.getClass(), destroyMethodName); 39 | if (destroyMethod == null) { 40 | throw new BeansException("Couldn't find a destroy method named '" + destroyMethodName + "' on bean with name '" + beanName + "'"); 41 | } 42 | destroyMethod.invoke(bean); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/support/InstantiationStrategy.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory.support; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.factory.config.BeanDefinition; 5 | 6 | /** 7 | * Bean的实例化策略 8 | * 9 | * @author derekyi 10 | * @date 2020/11/23 11 | */ 12 | public interface InstantiationStrategy { 13 | 14 | Object instantiate(BeanDefinition beanDefinition) throws BeansException; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/support/SimpleInstantiationStrategy.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory.support; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.factory.config.BeanDefinition; 5 | 6 | import java.lang.reflect.Constructor; 7 | 8 | /** 9 | * @author derekyi 10 | * @date 2020/11/23 11 | */ 12 | public class SimpleInstantiationStrategy implements InstantiationStrategy { 13 | 14 | /** 15 | * 简单的bean实例化策略,根据bean的无参构造函数实例化对象 16 | * 17 | * @param beanDefinition 18 | * @return 19 | * @throws BeansException 20 | */ 21 | @Override 22 | public Object instantiate(BeanDefinition beanDefinition) throws BeansException { 23 | Class beanClass = beanDefinition.getBeanClass(); 24 | try { 25 | Constructor constructor = beanClass.getDeclaredConstructor(); 26 | return constructor.newInstance(); 27 | } catch (Exception e) { 28 | throw new BeansException("Failed to instantiate [" + beanClass.getName() + "]", e); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/beans/factory/xml/XmlBeanDefinitionReader.java: -------------------------------------------------------------------------------- 1 | package org.springframework.beans.factory.xml; 2 | 3 | 4 | import cn.hutool.core.util.StrUtil; 5 | import org.dom4j.Document; 6 | import org.dom4j.DocumentException; 7 | import org.dom4j.Element; 8 | import org.dom4j.io.SAXReader; 9 | 10 | import org.springframework.beans.BeansException; 11 | import org.springframework.beans.PropertyValue; 12 | import org.springframework.beans.factory.config.BeanDefinition; 13 | import org.springframework.beans.factory.config.BeanReference; 14 | import org.springframework.beans.factory.support.AbstractBeanDefinitionReader; 15 | import org.springframework.beans.factory.support.BeanDefinitionRegistry; 16 | import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; 17 | import org.springframework.core.io.Resource; 18 | import org.springframework.core.io.ResourceLoader; 19 | 20 | import java.io.IOException; 21 | import java.io.InputStream; 22 | import java.util.List; 23 | 24 | /** 25 | * 读取配置在xml文件中的bean定义信息 26 | * 27 | * @author derekyi 28 | * @date 2020/11/26 29 | */ 30 | public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader { 31 | 32 | public static final String BEAN_ELEMENT = "bean"; 33 | public static final String PROPERTY_ELEMENT = "property"; 34 | public static final String ID_ATTRIBUTE = "id"; 35 | public static final String NAME_ATTRIBUTE = "name"; 36 | public static final String CLASS_ATTRIBUTE = "class"; 37 | public static final String VALUE_ATTRIBUTE = "value"; 38 | public static final String REF_ATTRIBUTE = "ref"; 39 | public static final String INIT_METHOD_ATTRIBUTE = "init-method"; 40 | public static final String DESTROY_METHOD_ATTRIBUTE = "destroy-method"; 41 | public static final String SCOPE_ATTRIBUTE = "scope"; 42 | public static final String LAZYINIT_ATTRIBUTE = "lazyInit"; 43 | public static final String BASE_PACKAGE_ATTRIBUTE = "base-package"; 44 | public static final String COMPONENT_SCAN_ELEMENT = "component-scan"; 45 | 46 | public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) { 47 | super(registry); 48 | } 49 | 50 | public XmlBeanDefinitionReader(BeanDefinitionRegistry registry, ResourceLoader resourceLoader) { 51 | super(registry, resourceLoader); 52 | } 53 | 54 | @Override 55 | public void loadBeanDefinitions(String location) throws BeansException { 56 | ResourceLoader resourceLoader = getResourceLoader(); 57 | Resource resource = resourceLoader.getResource(location); 58 | loadBeanDefinitions(resource); 59 | } 60 | 61 | @Override 62 | public void loadBeanDefinitions(Resource resource) throws BeansException { 63 | try { 64 | InputStream inputStream = resource.getInputStream(); 65 | try { 66 | doLoadBeanDefinitions(inputStream); 67 | } finally { 68 | inputStream.close(); 69 | } 70 | } catch (IOException | DocumentException ex) { 71 | throw new BeansException("IOException parsing XML document from " + resource, ex); 72 | } 73 | } 74 | 75 | protected void doLoadBeanDefinitions(InputStream inputStream) throws DocumentException { 76 | SAXReader reader = new SAXReader(); 77 | Document document = reader.read(inputStream); 78 | 79 | Element root = document.getRootElement(); 80 | 81 | //解析context:component-scan标签并扫描指定包中的类,提取类信息,组装成BeanDefinition 82 | Element componentScan = root.element(COMPONENT_SCAN_ELEMENT); 83 | if (componentScan != null) { 84 | String scanPath = componentScan.attributeValue(BASE_PACKAGE_ATTRIBUTE); 85 | if (StrUtil.isEmpty(scanPath)) { 86 | throw new BeansException("The value of base-package attribute can not be empty or null"); 87 | } 88 | scanPackage(scanPath); 89 | } 90 | 91 | List beanList = root.elements(BEAN_ELEMENT); 92 | for (Element bean : beanList) { 93 | String beanId = bean.attributeValue(ID_ATTRIBUTE); 94 | String beanName = bean.attributeValue(NAME_ATTRIBUTE); 95 | String className = bean.attributeValue(CLASS_ATTRIBUTE); 96 | String initMethodName = bean.attributeValue(INIT_METHOD_ATTRIBUTE); 97 | String destroyMethodName = bean.attributeValue(DESTROY_METHOD_ATTRIBUTE); 98 | String beanScope = bean.attributeValue(SCOPE_ATTRIBUTE); 99 | String lazyInit = bean.attributeValue(LAZYINIT_ATTRIBUTE); 100 | Class clazz; 101 | try { 102 | clazz = Class.forName(className); 103 | } catch (ClassNotFoundException e) { 104 | throw new BeansException("Cannot find class [" + className + "]"); 105 | } 106 | //id优先于name 107 | beanName = StrUtil.isNotEmpty(beanId) ? beanId : beanName; 108 | if (StrUtil.isEmpty(beanName)) { 109 | //如果id和name都为空,将类名的第一个字母转为小写后作为bean的名称 110 | beanName = StrUtil.lowerFirst(clazz.getSimpleName()); 111 | } 112 | 113 | BeanDefinition beanDefinition = new BeanDefinition(clazz); 114 | beanDefinition.setInitMethodName(initMethodName); 115 | beanDefinition.setDestroyMethodName(destroyMethodName); 116 | beanDefinition.setLazyInit(Boolean.parseBoolean(lazyInit)); 117 | if (StrUtil.isNotEmpty(beanScope)) { 118 | beanDefinition.setScope(beanScope); 119 | } 120 | 121 | List propertyList = bean.elements(PROPERTY_ELEMENT); 122 | for (Element property : propertyList) { 123 | String propertyNameAttribute = property.attributeValue(NAME_ATTRIBUTE); 124 | String propertyValueAttribute = property.attributeValue(VALUE_ATTRIBUTE); 125 | String propertyRefAttribute = property.attributeValue(REF_ATTRIBUTE); 126 | 127 | if (StrUtil.isEmpty(propertyNameAttribute)) { 128 | throw new BeansException("The name attribute cannot be null or empty"); 129 | } 130 | 131 | Object value = propertyValueAttribute; 132 | if (StrUtil.isNotEmpty(propertyRefAttribute)) { 133 | value = new BeanReference(propertyRefAttribute); 134 | } 135 | PropertyValue propertyValue = new PropertyValue(propertyNameAttribute, value); 136 | beanDefinition.getPropertyValues().addPropertyValue(propertyValue); 137 | } 138 | if (getRegistry().containsBeanDefinition(beanName)) { 139 | //beanName不能重名 140 | throw new BeansException("Duplicate beanName[" + beanName + "] is not allowed"); 141 | } 142 | //注册BeanDefinition 143 | getRegistry().registerBeanDefinition(beanName, beanDefinition); 144 | } 145 | } 146 | 147 | /** 148 | * 扫描注解Component的类,提取信息,组装成BeanDefinition 149 | * 150 | * @param scanPath 151 | */ 152 | private void scanPackage(String scanPath) { 153 | String[] basePackages = StrUtil.splitToArray(scanPath, ','); 154 | ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(getRegistry()); 155 | scanner.doScan(basePackages); 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/context/ApplicationContext.java: -------------------------------------------------------------------------------- 1 | package org.springframework.context; 2 | 3 | import org.springframework.beans.factory.HierarchicalBeanFactory; 4 | import org.springframework.beans.factory.ListableBeanFactory; 5 | import org.springframework.core.io.ResourceLoader; 6 | 7 | /** 8 | * 应用上下文 9 | * 10 | * @author derekyi 11 | * @date 2020/11/28 12 | */ 13 | public interface ApplicationContext extends ListableBeanFactory, HierarchicalBeanFactory, ResourceLoader, ApplicationEventPublisher { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/context/ApplicationContextAware.java: -------------------------------------------------------------------------------- 1 | package org.springframework.context; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.factory.Aware; 5 | 6 | /** 7 | * 实现该接口,能感知所属ApplicationContext 8 | * 9 | * @author derekyi 10 | * @date 2020/12/1 11 | */ 12 | public interface ApplicationContextAware extends Aware { 13 | 14 | void setApplicationContext(ApplicationContext applicationContext) throws BeansException; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/context/ApplicationEvent.java: -------------------------------------------------------------------------------- 1 | package org.springframework.context; 2 | 3 | import java.util.EventObject; 4 | 5 | /** 6 | * @author derekyi 7 | * @date 2020/12/2 8 | */ 9 | public abstract class ApplicationEvent extends EventObject { 10 | 11 | public ApplicationEvent(Object source) { 12 | super(source); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/context/ApplicationEventPublisher.java: -------------------------------------------------------------------------------- 1 | package org.springframework.context; 2 | 3 | /** 4 | * 事件发布者接口 5 | * 6 | * @author derekyi 7 | * @date 2020/12/5 8 | */ 9 | public interface ApplicationEventPublisher { 10 | 11 | /** 12 | * 发布事件 13 | * 14 | * @param event 15 | */ 16 | void publishEvent(ApplicationEvent event); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/context/ApplicationListener.java: -------------------------------------------------------------------------------- 1 | package org.springframework.context; 2 | 3 | import java.util.EventListener; 4 | 5 | /** 6 | * @author derekyi 7 | * @date 2020/12/2 8 | */ 9 | public interface ApplicationListener extends EventListener { 10 | 11 | void onApplicationEvent(E event); 12 | } -------------------------------------------------------------------------------- /src/main/java/org/springframework/context/ConfigurableApplicationContext.java: -------------------------------------------------------------------------------- 1 | package org.springframework.context; 2 | 3 | import org.springframework.beans.BeansException; 4 | 5 | /** 6 | * @author derekyi 7 | * @date 2020/11/28 8 | */ 9 | public interface ConfigurableApplicationContext extends ApplicationContext { 10 | 11 | /** 12 | * 刷新容器 13 | * 14 | * @throws BeansException 15 | */ 16 | void refresh() throws BeansException; 17 | 18 | /** 19 | * 关闭应用上下文 20 | */ 21 | void close(); 22 | 23 | /** 24 | * 向虚拟机中注册一个钩子方法,在虚拟机关闭之前执行关闭容器等操作 25 | */ 26 | void registerShutdownHook(); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/context/annotation/ClassPathBeanDefinitionScanner.java: -------------------------------------------------------------------------------- 1 | package org.springframework.context.annotation; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor; 5 | import org.springframework.beans.factory.config.BeanDefinition; 6 | import org.springframework.beans.factory.support.BeanDefinitionRegistry; 7 | import org.springframework.stereotype.Component; 8 | 9 | import java.util.Set; 10 | 11 | /** 12 | * @author derekyi 13 | * @date 2020/12/26 14 | */ 15 | public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider { 16 | 17 | public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"; 18 | 19 | private BeanDefinitionRegistry registry; 20 | 21 | public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) { 22 | this.registry = registry; 23 | } 24 | 25 | public void doScan(String... basePackages) { 26 | for (String basePackage : basePackages) { 27 | Set candidates = findCandidateComponents(basePackage); 28 | for (BeanDefinition candidate : candidates) { 29 | // 解析bean的作用域 30 | String beanScope = resolveBeanScope(candidate); 31 | if (StrUtil.isNotEmpty(beanScope)) { 32 | candidate.setScope(beanScope); 33 | } 34 | //生成bean的名称 35 | String beanName = determineBeanName(candidate); 36 | //注册BeanDefinition 37 | registry.registerBeanDefinition(beanName, candidate); 38 | } 39 | } 40 | 41 | //注册处理@Autowired和@Value注解的BeanPostProcessor 42 | registry.registerBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME, new BeanDefinition(AutowiredAnnotationBeanPostProcessor.class)); 43 | } 44 | 45 | /** 46 | * 获取bean的作用域 47 | * 48 | * @param beanDefinition 49 | * @return 50 | */ 51 | private String resolveBeanScope(BeanDefinition beanDefinition) { 52 | Class beanClass = beanDefinition.getBeanClass(); 53 | Scope scope = beanClass.getAnnotation(Scope.class); 54 | if (scope != null) { 55 | return scope.value(); 56 | } 57 | 58 | return StrUtil.EMPTY; 59 | } 60 | 61 | 62 | /** 63 | * 生成bean的名称 64 | * 65 | * @param beanDefinition 66 | * @return 67 | */ 68 | private String determineBeanName(BeanDefinition beanDefinition) { 69 | Class beanClass = beanDefinition.getBeanClass(); 70 | Component component = beanClass.getAnnotation(Component.class); 71 | String value = component.value(); 72 | if (StrUtil.isEmpty(value)) { 73 | value = StrUtil.lowerFirst(beanClass.getSimpleName()); 74 | } 75 | return value; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/context/annotation/ClassPathScanningCandidateComponentProvider.java: -------------------------------------------------------------------------------- 1 | package org.springframework.context.annotation; 2 | 3 | import cn.hutool.core.util.ClassUtil; 4 | import org.springframework.beans.factory.config.BeanDefinition; 5 | import org.springframework.stereotype.Component; 6 | 7 | import java.util.LinkedHashSet; 8 | import java.util.Set; 9 | 10 | /** 11 | * @author derekyi 12 | * @date 2020/12/26 13 | */ 14 | public class ClassPathScanningCandidateComponentProvider { 15 | 16 | public Set findCandidateComponents(String basePackage) { 17 | Set candidates = new LinkedHashSet(); 18 | // 扫描有org.springframework.stereotype.Component注解的类 19 | Set> classes = ClassUtil.scanPackageByAnnotation(basePackage, Component.class); 20 | for (Class clazz : classes) { 21 | BeanDefinition beanDefinition = new BeanDefinition(clazz); 22 | candidates.add(beanDefinition); 23 | } 24 | return candidates; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/context/annotation/Scope.java: -------------------------------------------------------------------------------- 1 | package org.springframework.context.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @author derekyi 7 | * @date 2020/12/26 8 | */ 9 | @Target({ElementType.TYPE, ElementType.METHOD}) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Documented 12 | public @interface Scope { 13 | 14 | String value() default "singleton"; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/context/event/AbstractApplicationEventMulticaster.java: -------------------------------------------------------------------------------- 1 | package org.springframework.context.event; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.factory.BeanFactory; 5 | import org.springframework.beans.factory.BeanFactoryAware; 6 | import org.springframework.context.ApplicationEvent; 7 | import org.springframework.context.ApplicationListener; 8 | 9 | import java.util.HashSet; 10 | import java.util.Set; 11 | 12 | /** 13 | * @author derekyi 14 | * @date 2020/12/5 15 | */ 16 | public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster, BeanFactoryAware { 17 | 18 | public final Set> applicationListeners = new HashSet<>(); 19 | 20 | private BeanFactory beanFactory; 21 | 22 | @Override 23 | public void addApplicationListener(ApplicationListener listener) { 24 | applicationListeners.add((ApplicationListener) listener); 25 | } 26 | 27 | @Override 28 | public void removeApplicationListener(ApplicationListener listener) { 29 | applicationListeners.remove(listener); 30 | } 31 | 32 | @Override 33 | public void setBeanFactory(BeanFactory beanFactory) throws BeansException { 34 | this.beanFactory = beanFactory; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/context/event/ApplicationContextEvent.java: -------------------------------------------------------------------------------- 1 | package org.springframework.context.event; 2 | 3 | import org.springframework.context.ApplicationContext; 4 | import org.springframework.context.ApplicationEvent; 5 | 6 | /** 7 | * @author derekyi 8 | * @date 2020/12/2 9 | */ 10 | public abstract class ApplicationContextEvent extends ApplicationEvent { 11 | 12 | public ApplicationContextEvent(ApplicationContext source) { 13 | super(source); 14 | } 15 | 16 | public final ApplicationContext getApplicationContext() { 17 | return (ApplicationContext) getSource(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/context/event/ApplicationEventMulticaster.java: -------------------------------------------------------------------------------- 1 | package org.springframework.context.event; 2 | 3 | import org.springframework.context.ApplicationEvent; 4 | import org.springframework.context.ApplicationListener; 5 | 6 | /** 7 | * @author derekyi 8 | * @date 2020/12/5 9 | */ 10 | public interface ApplicationEventMulticaster { 11 | 12 | void addApplicationListener(ApplicationListener listener); 13 | 14 | void removeApplicationListener(ApplicationListener listener); 15 | 16 | void multicastEvent(ApplicationEvent event); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/context/event/ContextClosedEvent.java: -------------------------------------------------------------------------------- 1 | package org.springframework.context.event; 2 | 3 | import org.springframework.context.ApplicationContext; 4 | 5 | /** 6 | * @author derekyi 7 | * @date 2020/12/2 8 | */ 9 | public class ContextClosedEvent extends ApplicationContextEvent { 10 | 11 | public ContextClosedEvent(ApplicationContext source) { 12 | super(source); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/context/event/ContextRefreshedEvent.java: -------------------------------------------------------------------------------- 1 | package org.springframework.context.event; 2 | 3 | import org.springframework.context.ApplicationContext; 4 | 5 | /** 6 | * @author derekyi 7 | * @date 2020/12/2 8 | */ 9 | public class ContextRefreshedEvent extends ApplicationContextEvent { 10 | 11 | public ContextRefreshedEvent(ApplicationContext source) { 12 | super(source); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/context/event/SimpleApplicationEventMulticaster.java: -------------------------------------------------------------------------------- 1 | package org.springframework.context.event; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.factory.BeanFactory; 5 | import org.springframework.context.ApplicationEvent; 6 | import org.springframework.context.ApplicationListener; 7 | 8 | import java.lang.reflect.ParameterizedType; 9 | import java.lang.reflect.Type; 10 | 11 | /** 12 | * @author derekyi 13 | * @date 2020/12/5 14 | */ 15 | public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster { 16 | 17 | public SimpleApplicationEventMulticaster(BeanFactory beanFactory) { 18 | setBeanFactory(beanFactory); 19 | } 20 | 21 | @Override 22 | public void multicastEvent(ApplicationEvent event) { 23 | for (ApplicationListener applicationListener : applicationListeners) { 24 | if (supportsEvent(applicationListener, event)) { 25 | applicationListener.onApplicationEvent(event); 26 | } 27 | } 28 | } 29 | 30 | /** 31 | * 监听器是否对该事件感兴趣 32 | * 33 | * @param applicationListener 34 | * @param event 35 | * @return 36 | */ 37 | protected boolean supportsEvent(ApplicationListener applicationListener, ApplicationEvent event) { 38 | Type type = applicationListener.getClass().getGenericInterfaces()[0]; 39 | Type actualTypeArgument = ((ParameterizedType) type).getActualTypeArguments()[0]; 40 | String className = actualTypeArgument.getTypeName(); 41 | Class eventClassName; 42 | try { 43 | eventClassName = Class.forName(className); 44 | } catch (ClassNotFoundException e) { 45 | throw new BeansException("wrong event class name: " + className); 46 | } 47 | return eventClassName.isAssignableFrom(event.getClass()); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/context/support/AbstractApplicationContext.java: -------------------------------------------------------------------------------- 1 | package org.springframework.context.support; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.factory.ConfigurableListableBeanFactory; 5 | import org.springframework.beans.factory.config.BeanFactoryPostProcessor; 6 | import org.springframework.beans.factory.config.BeanPostProcessor; 7 | import org.springframework.context.ApplicationEvent; 8 | import org.springframework.context.ApplicationListener; 9 | import org.springframework.context.ConfigurableApplicationContext; 10 | import org.springframework.context.event.ApplicationEventMulticaster; 11 | import org.springframework.context.event.ContextClosedEvent; 12 | import org.springframework.context.event.ContextRefreshedEvent; 13 | import org.springframework.context.event.SimpleApplicationEventMulticaster; 14 | import org.springframework.core.convert.ConversionService; 15 | import org.springframework.core.io.DefaultResourceLoader; 16 | 17 | import java.util.Collection; 18 | import java.util.Map; 19 | 20 | /** 21 | * 抽象应用上下文 22 | * 23 | * @author derekyi 24 | * @date 2020/11/28 25 | */ 26 | public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext { 27 | 28 | public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster"; 29 | 30 | public static final String CONVERSION_SERVICE_BEAN_NAME = "conversionService"; 31 | 32 | private ApplicationEventMulticaster applicationEventMulticaster; 33 | 34 | @Override 35 | public void refresh() throws BeansException { 36 | //创建BeanFactory,并加载BeanDefinition 37 | refreshBeanFactory(); 38 | ConfigurableListableBeanFactory beanFactory = getBeanFactory(); 39 | 40 | //添加ApplicationContextAwareProcessor,让继承自ApplicationContextAware的bean能感知bean 41 | beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); 42 | 43 | //在bean实例化之前,执行BeanFactoryPostProcessor 44 | invokeBeanFactoryPostProcessors(beanFactory); 45 | 46 | //BeanPostProcessor需要提前与其他bean实例化之前注册 47 | registerBeanPostProcessors(beanFactory); 48 | 49 | //初始化事件发布者 50 | initApplicationEventMulticaster(); 51 | 52 | //注册事件监听器 53 | registerListeners(); 54 | 55 | //注册类型转换器和提前实例化单例bean 56 | finishBeanFactoryInitialization(beanFactory); 57 | 58 | //发布容器刷新完成事件 59 | finishRefresh(); 60 | } 61 | 62 | protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { 63 | //设置类型转换器 64 | if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME)) { 65 | Object conversionService = beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME); 66 | if (conversionService instanceof ConversionService) { 67 | beanFactory.setConversionService((ConversionService) conversionService); 68 | } 69 | } 70 | 71 | //提前实例化单例bean 72 | beanFactory.preInstantiateSingletons(); 73 | } 74 | 75 | /** 76 | * 创建BeanFactory,并加载BeanDefinition 77 | * 78 | * @throws BeansException 79 | */ 80 | protected abstract void refreshBeanFactory() throws BeansException; 81 | 82 | /** 83 | * 在bean实例化之前,执行BeanFactoryPostProcessor 84 | * 85 | * @param beanFactory 86 | */ 87 | protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { 88 | Map beanFactoryPostProcessorMap = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class); 89 | for (BeanFactoryPostProcessor beanFactoryPostProcessor : beanFactoryPostProcessorMap.values()) { 90 | beanFactoryPostProcessor.postProcessBeanFactory(beanFactory); 91 | } 92 | } 93 | 94 | /** 95 | * 注册BeanPostProcessor 96 | * 97 | * @param beanFactory 98 | */ 99 | protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) { 100 | Map beanPostProcessorMap = beanFactory.getBeansOfType(BeanPostProcessor.class); 101 | for (BeanPostProcessor beanPostProcessor : beanPostProcessorMap.values()) { 102 | beanFactory.addBeanPostProcessor(beanPostProcessor); 103 | } 104 | } 105 | 106 | /** 107 | * 初始化事件发布者 108 | */ 109 | protected void initApplicationEventMulticaster() { 110 | ConfigurableListableBeanFactory beanFactory = getBeanFactory(); 111 | applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); 112 | beanFactory.addSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, applicationEventMulticaster); 113 | } 114 | 115 | /** 116 | * 注册事件监听器 117 | */ 118 | protected void registerListeners() { 119 | Collection applicationListeners = getBeansOfType(ApplicationListener.class).values(); 120 | for (ApplicationListener applicationListener : applicationListeners) { 121 | applicationEventMulticaster.addApplicationListener(applicationListener); 122 | } 123 | } 124 | 125 | /** 126 | * 发布容器刷新完成事件 127 | */ 128 | protected void finishRefresh() { 129 | publishEvent(new ContextRefreshedEvent(this)); 130 | } 131 | 132 | @Override 133 | public void publishEvent(ApplicationEvent event) { 134 | applicationEventMulticaster.multicastEvent(event); 135 | } 136 | 137 | @Override 138 | public boolean containsBean(String name) { 139 | return getBeanFactory().containsBean(name); 140 | } 141 | 142 | @Override 143 | public T getBean(String name, Class requiredType) throws BeansException { 144 | return getBeanFactory().getBean(name, requiredType); 145 | } 146 | 147 | @Override 148 | public Map getBeansOfType(Class type) throws BeansException { 149 | return getBeanFactory().getBeansOfType(type); 150 | } 151 | 152 | public T getBean(Class requiredType) throws BeansException { 153 | return getBeanFactory().getBean(requiredType); 154 | } 155 | 156 | @Override 157 | public Object getBean(String name) throws BeansException { 158 | return getBeanFactory().getBean(name); 159 | } 160 | 161 | public String[] getBeanDefinitionNames() { 162 | return getBeanFactory().getBeanDefinitionNames(); 163 | } 164 | 165 | public abstract ConfigurableListableBeanFactory getBeanFactory(); 166 | 167 | public void close() { 168 | doClose(); 169 | } 170 | 171 | public void registerShutdownHook() { 172 | Thread shutdownHook = new Thread() { 173 | public void run() { 174 | doClose(); 175 | } 176 | }; 177 | Runtime.getRuntime().addShutdownHook(shutdownHook); 178 | 179 | } 180 | 181 | protected void doClose() { 182 | //发布容器关闭事件 183 | publishEvent(new ContextClosedEvent(this)); 184 | 185 | //执行单例bean的销毁方法 186 | destroyBeans(); 187 | } 188 | 189 | protected void destroyBeans() { 190 | getBeanFactory().destroySingletons(); 191 | } 192 | } 193 | 194 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/context/support/AbstractRefreshableApplicationContext.java: -------------------------------------------------------------------------------- 1 | package org.springframework.context.support; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.factory.support.DefaultListableBeanFactory; 5 | 6 | /** 7 | * @author derekyi 8 | * @date 2020/11/28 9 | */ 10 | public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext { 11 | 12 | private DefaultListableBeanFactory beanFactory; 13 | 14 | /** 15 | * 创建beanFactory并加载BeanDefinition 16 | * 17 | * @throws BeansException 18 | */ 19 | protected final void refreshBeanFactory() throws BeansException { 20 | DefaultListableBeanFactory beanFactory = createBeanFactory(); 21 | loadBeanDefinitions(beanFactory); 22 | this.beanFactory = beanFactory; 23 | } 24 | 25 | /** 26 | * 创建bean工厂 27 | * 28 | * @return 29 | */ 30 | protected DefaultListableBeanFactory createBeanFactory() { 31 | return new DefaultListableBeanFactory(); 32 | } 33 | 34 | /** 35 | * 加载BeanDefinition 36 | * 37 | * @param beanFactory 38 | * @throws BeansException 39 | */ 40 | protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException; 41 | 42 | public DefaultListableBeanFactory getBeanFactory() { 43 | return beanFactory; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/context/support/AbstractXmlApplicationContext.java: -------------------------------------------------------------------------------- 1 | package org.springframework.context.support; 2 | 3 | import org.springframework.beans.factory.support.DefaultListableBeanFactory; 4 | import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; 5 | 6 | /** 7 | * @author derekyi 8 | * @date 2020/11/28 9 | */ 10 | public abstract class AbstractXmlApplicationContext extends AbstractRefreshableApplicationContext { 11 | 12 | protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) { 13 | XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory, this); 14 | String[] configLocations = getConfigLocations(); 15 | if (configLocations != null) { 16 | beanDefinitionReader.loadBeanDefinitions(configLocations); 17 | } 18 | } 19 | 20 | protected abstract String[] getConfigLocations(); 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/context/support/ApplicationContextAwareProcessor.java: -------------------------------------------------------------------------------- 1 | package org.springframework.context.support; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.factory.config.BeanPostProcessor; 5 | import org.springframework.context.ApplicationContext; 6 | import org.springframework.context.ApplicationContextAware; 7 | 8 | /** 9 | * @author derekyi 10 | * @date 2020/12/1 11 | */ 12 | public class ApplicationContextAwareProcessor implements BeanPostProcessor { 13 | 14 | private final ApplicationContext applicationContext; 15 | 16 | public ApplicationContextAwareProcessor(ApplicationContext applicationContext) { 17 | this.applicationContext = applicationContext; 18 | } 19 | 20 | @Override 21 | public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 22 | if (bean instanceof ApplicationContextAware) { 23 | ((ApplicationContextAware) bean).setApplicationContext(applicationContext); 24 | } 25 | return bean; 26 | } 27 | 28 | @Override 29 | public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 30 | return bean; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/context/support/ClassPathXmlApplicationContext.java: -------------------------------------------------------------------------------- 1 | package org.springframework.context.support; 2 | 3 | import org.springframework.beans.BeansException; 4 | 5 | /** 6 | * xml文件的应用上下文 7 | * 8 | * @author derekyi 9 | * @date 2020/11/28 10 | */ 11 | public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext { 12 | 13 | private String[] configLocations; 14 | 15 | /** 16 | * 从xml文件加载BeanDefinition,并且自动刷新上下文 17 | * 18 | * @param configLocation xml配置文件 19 | * @throws BeansException 应用上下文创建失败 20 | */ 21 | public ClassPathXmlApplicationContext(String configLocation) throws BeansException { 22 | this(new String[]{configLocation}); 23 | } 24 | 25 | /** 26 | * 从xml文件加载BeanDefinition,并且自动刷新上下文 27 | * 28 | * @param configLocations xml配置文件 29 | * @throws BeansException 应用上下文创建失败 30 | */ 31 | public ClassPathXmlApplicationContext(String[] configLocations) throws BeansException { 32 | this.configLocations = configLocations; 33 | refresh(); 34 | } 35 | 36 | protected String[] getConfigLocations() { 37 | return this.configLocations; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/context/support/ConversionServiceFactoryBean.java: -------------------------------------------------------------------------------- 1 | package org.springframework.context.support; 2 | 3 | import org.springframework.beans.factory.FactoryBean; 4 | import org.springframework.beans.factory.InitializingBean; 5 | import org.springframework.core.convert.ConversionService; 6 | import org.springframework.core.convert.converter.Converter; 7 | import org.springframework.core.convert.converter.ConverterFactory; 8 | import org.springframework.core.convert.converter.ConverterRegistry; 9 | import org.springframework.core.convert.converter.GenericConverter; 10 | import org.springframework.core.convert.support.DefaultConversionService; 11 | import org.springframework.core.convert.support.GenericConversionService; 12 | 13 | import java.util.Set; 14 | 15 | /** 16 | * @author derekyi 17 | * @date 2021/1/17 18 | */ 19 | public class ConversionServiceFactoryBean implements FactoryBean, InitializingBean { 20 | 21 | private Set converters; 22 | 23 | private GenericConversionService conversionService; 24 | 25 | @Override 26 | public void afterPropertiesSet() throws Exception { 27 | conversionService = new DefaultConversionService(); 28 | registerConverters(converters, conversionService); 29 | } 30 | 31 | private void registerConverters(Set converters, ConverterRegistry registry) { 32 | if (converters != null) { 33 | for (Object converter : converters) { 34 | if (converter instanceof GenericConverter) { 35 | registry.addConverter((GenericConverter) converter); 36 | } else if (converter instanceof Converter) { 37 | registry.addConverter((Converter) converter); 38 | } else if (converter instanceof ConverterFactory) { 39 | registry.addConverterFactory((ConverterFactory) converter); 40 | } else { 41 | throw new IllegalArgumentException("Each converter object must implement one of the " + 42 | "Converter, ConverterFactory, or GenericConverter interfaces"); 43 | } 44 | } 45 | } 46 | } 47 | 48 | @Override 49 | public ConversionService getObject() throws Exception { 50 | return conversionService; 51 | } 52 | 53 | @Override 54 | public boolean isSingleton() { 55 | return true; 56 | } 57 | 58 | public void setConverters(Set converters) { 59 | this.converters = converters; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/core/convert/ConversionService.java: -------------------------------------------------------------------------------- 1 | package org.springframework.core.convert; 2 | 3 | /** 4 | * 类型转换抽象接口 5 | * 6 | * @author derekyi 7 | * @date 2021/1/10 8 | */ 9 | public interface ConversionService { 10 | 11 | boolean canConvert(Class sourceType, Class targetType); 12 | 13 | T convert(Object source, Class targetType); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/core/convert/converter/Converter.java: -------------------------------------------------------------------------------- 1 | package org.springframework.core.convert.converter; 2 | 3 | /** 4 | * 类型转换抽象接口 5 | * 6 | * @author derekyi 7 | * @date 2021/1/10 8 | */ 9 | public interface Converter { 10 | 11 | /** 12 | * 类型转换 13 | */ 14 | T convert(S source); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/core/convert/converter/ConverterFactory.java: -------------------------------------------------------------------------------- 1 | package org.springframework.core.convert.converter; 2 | 3 | /** 4 | * 类型转换工厂 5 | * 6 | * @author derekyi 7 | * @date 2021/1/10 8 | */ 9 | public interface ConverterFactory { 10 | 11 | Converter getConverter(Class targetType); 12 | } -------------------------------------------------------------------------------- /src/main/java/org/springframework/core/convert/converter/ConverterRegistry.java: -------------------------------------------------------------------------------- 1 | package org.springframework.core.convert.converter; 2 | 3 | /** 4 | * 类型转换器注册接口 5 | * 6 | * @author derekyi 7 | * @date 2021/1/10 8 | */ 9 | public interface ConverterRegistry { 10 | 11 | void addConverter(Converter converter); 12 | 13 | void addConverterFactory(ConverterFactory converterFactory); 14 | 15 | void addConverter(GenericConverter converter); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/core/convert/converter/GenericConverter.java: -------------------------------------------------------------------------------- 1 | package org.springframework.core.convert.converter; 2 | 3 | import java.util.Set; 4 | 5 | /** 6 | * @author derekyi 7 | * @date 2021/1/16 8 | */ 9 | public interface GenericConverter { 10 | 11 | Set getConvertibleTypes(); 12 | 13 | Object convert(Object source, Class sourceType, Class targetType); 14 | 15 | public static final class ConvertiblePair { 16 | 17 | private final Class sourceType; 18 | 19 | private final Class targetType; 20 | 21 | public ConvertiblePair(Class sourceType, Class targetType) { 22 | this.sourceType = sourceType; 23 | this.targetType = targetType; 24 | } 25 | 26 | public Class getSourceType() { 27 | return this.sourceType; 28 | } 29 | 30 | public Class getTargetType() { 31 | return this.targetType; 32 | } 33 | 34 | @Override 35 | public boolean equals(Object obj) { 36 | if (this == obj) { 37 | return true; 38 | } 39 | if (obj == null || obj.getClass() != ConvertiblePair.class) { 40 | return false; 41 | } 42 | ConvertiblePair other = (ConvertiblePair) obj; 43 | return this.sourceType.equals(other.sourceType) && this.targetType.equals(other.targetType); 44 | 45 | } 46 | 47 | @Override 48 | public int hashCode() { 49 | return this.sourceType.hashCode() * 31 + this.targetType.hashCode(); 50 | } 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/core/convert/support/DefaultConversionService.java: -------------------------------------------------------------------------------- 1 | package org.springframework.core.convert.support; 2 | 3 | import org.springframework.core.convert.converter.ConverterRegistry; 4 | 5 | /** 6 | * @author derekyi 7 | * @date 2021/1/16 8 | */ 9 | public class DefaultConversionService extends GenericConversionService { 10 | 11 | public DefaultConversionService() { 12 | addDefaultConverters(this); 13 | } 14 | 15 | public static void addDefaultConverters(ConverterRegistry converterRegistry) { 16 | converterRegistry.addConverterFactory(new StringToNumberConverterFactory()); 17 | //TODO 添加其他ConverterFactory 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/core/convert/support/GenericConversionService.java: -------------------------------------------------------------------------------- 1 | package org.springframework.core.convert.support; 2 | 3 | import cn.hutool.core.convert.BasicType; 4 | import org.springframework.core.convert.ConversionService; 5 | import org.springframework.core.convert.converter.Converter; 6 | import org.springframework.core.convert.converter.ConverterFactory; 7 | import org.springframework.core.convert.converter.ConverterRegistry; 8 | import org.springframework.core.convert.converter.GenericConverter; 9 | import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair; 10 | 11 | import java.lang.reflect.ParameterizedType; 12 | import java.lang.reflect.Type; 13 | import java.util.*; 14 | 15 | /** 16 | * @author derekyi 17 | * @date 2021/1/16 18 | */ 19 | public class GenericConversionService implements ConversionService, ConverterRegistry { 20 | 21 | private Map converters = new HashMap<>(); 22 | 23 | @Override 24 | public boolean canConvert(Class sourceType, Class targetType) { 25 | GenericConverter converter = getConverter(sourceType, targetType); 26 | return converter != null; 27 | } 28 | 29 | @Override 30 | public T convert(Object source, Class targetType) { 31 | Class sourceType = source.getClass(); 32 | targetType = (Class) BasicType.wrap(targetType); 33 | GenericConverter converter = getConverter(sourceType, targetType); 34 | return (T) converter.convert(source, sourceType, targetType); 35 | } 36 | 37 | @Override 38 | public void addConverter(Converter converter) { 39 | ConvertiblePair typeInfo = getRequiredTypeInfo(converter); 40 | ConverterAdapter converterAdapter = new ConverterAdapter(typeInfo, converter); 41 | for (ConvertiblePair convertibleType : converterAdapter.getConvertibleTypes()) { 42 | converters.put(convertibleType, converterAdapter); 43 | } 44 | } 45 | 46 | @Override 47 | public void addConverterFactory(ConverterFactory converterFactory) { 48 | ConvertiblePair typeInfo = getRequiredTypeInfo(converterFactory); 49 | ConverterFactoryAdapter converterFactoryAdapter = new ConverterFactoryAdapter(typeInfo, converterFactory); 50 | for (ConvertiblePair convertibleType : converterFactoryAdapter.getConvertibleTypes()) { 51 | converters.put(convertibleType, converterFactoryAdapter); 52 | } 53 | } 54 | 55 | @Override 56 | public void addConverter(GenericConverter converter) { 57 | for (ConvertiblePair convertibleType : converter.getConvertibleTypes()) { 58 | converters.put(convertibleType, converter); 59 | } 60 | } 61 | 62 | private ConvertiblePair getRequiredTypeInfo(Object object) { 63 | Type[] types = object.getClass().getGenericInterfaces(); 64 | ParameterizedType parameterized = (ParameterizedType) types[0]; 65 | Type[] actualTypeArguments = parameterized.getActualTypeArguments(); 66 | Class sourceType = (Class) actualTypeArguments[0]; 67 | Class targetType = (Class) actualTypeArguments[1]; 68 | return new ConvertiblePair(sourceType, targetType); 69 | } 70 | 71 | protected GenericConverter getConverter(Class sourceType, Class targetType) { 72 | List> sourceCandidates = getClassHierarchy(sourceType); 73 | List> targetCandidates = getClassHierarchy(targetType); 74 | for (Class sourceCandidate : sourceCandidates) { 75 | for (Class targetCandidate : targetCandidates) { 76 | ConvertiblePair convertiblePair = new ConvertiblePair(sourceCandidate, targetCandidate); 77 | GenericConverter converter = converters.get(convertiblePair); 78 | if (converter != null) { 79 | return converter; 80 | } 81 | } 82 | } 83 | return null; 84 | } 85 | 86 | private List> getClassHierarchy(Class clazz) { 87 | List> hierarchy = new ArrayList<>(); 88 | //原始类转为包装类 89 | clazz = BasicType.wrap(clazz); 90 | while (clazz != null) { 91 | hierarchy.add(clazz); 92 | clazz = clazz.getSuperclass(); 93 | } 94 | return hierarchy; 95 | } 96 | 97 | private final class ConverterAdapter implements GenericConverter { 98 | 99 | private final ConvertiblePair typeInfo; 100 | 101 | private final Converter converter; 102 | 103 | public ConverterAdapter(ConvertiblePair typeInfo, Converter converter) { 104 | this.typeInfo = typeInfo; 105 | this.converter = (Converter) converter; 106 | } 107 | 108 | @Override 109 | public Set getConvertibleTypes() { 110 | return Collections.singleton(typeInfo); 111 | } 112 | 113 | @Override 114 | public Object convert(Object source, Class sourceType, Class targetType) { 115 | return converter.convert(source); 116 | } 117 | } 118 | 119 | private final class ConverterFactoryAdapter implements GenericConverter { 120 | 121 | private final ConvertiblePair typeInfo; 122 | 123 | private final ConverterFactory converterFactory; 124 | 125 | public ConverterFactoryAdapter(ConvertiblePair typeInfo, ConverterFactory converterFactory) { 126 | this.typeInfo = typeInfo; 127 | this.converterFactory = (ConverterFactory) converterFactory; 128 | } 129 | 130 | @Override 131 | public Set getConvertibleTypes() { 132 | return Collections.singleton(typeInfo); 133 | } 134 | 135 | @Override 136 | public Object convert(Object source, Class sourceType, Class targetType) { 137 | return converterFactory.getConverter(targetType).convert(source); 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/core/convert/support/StringToNumberConverterFactory.java: -------------------------------------------------------------------------------- 1 | package org.springframework.core.convert.support; 2 | 3 | import org.springframework.core.convert.converter.Converter; 4 | import org.springframework.core.convert.converter.ConverterFactory; 5 | 6 | /** 7 | * @author derekyi 8 | * @date 2021/1/10 9 | */ 10 | public class StringToNumberConverterFactory implements ConverterFactory { 11 | 12 | @Override 13 | public Converter getConverter(Class targetType) { 14 | return new StringToNumber(targetType); 15 | } 16 | 17 | private static final class StringToNumber implements Converter { 18 | 19 | private final Class targetType; 20 | 21 | public StringToNumber(Class targetType) { 22 | this.targetType = targetType; 23 | } 24 | 25 | @Override 26 | public T convert(String source) { 27 | if (source.length() == 0) { 28 | return null; 29 | } 30 | 31 | if (targetType.equals(Integer.class)) { 32 | return (T) Integer.valueOf(source); 33 | } else if (targetType.equals(Long.class)) { 34 | return (T) Long.valueOf(source); 35 | } 36 | //TODO 其他数字类型 37 | 38 | else { 39 | throw new IllegalArgumentException( 40 | "Cannot convert String [" + source + "] to target class [" + targetType.getName() + "]"); 41 | } 42 | } 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /src/main/java/org/springframework/core/io/ClassPathResource.java: -------------------------------------------------------------------------------- 1 | package org.springframework.core.io; 2 | 3 | import java.io.FileNotFoundException; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | 7 | /** 8 | * classpath下的资源 9 | * 10 | * @author derekyi 11 | * @date 2020/11/25 12 | */ 13 | public class ClassPathResource implements Resource { 14 | 15 | private final String path; 16 | 17 | public ClassPathResource(String path) { 18 | this.path = path; 19 | } 20 | 21 | @Override 22 | public InputStream getInputStream() throws IOException { 23 | InputStream is = this.getClass().getClassLoader().getResourceAsStream(this.path); 24 | if (is == null) { 25 | throw new FileNotFoundException(this.path + " cannot be opened because it does not exist"); 26 | } 27 | return is; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/core/io/DefaultResourceLoader.java: -------------------------------------------------------------------------------- 1 | package org.springframework.core.io; 2 | 3 | import java.net.MalformedURLException; 4 | import java.net.URL; 5 | 6 | /** 7 | * @author derekyi 8 | * @date 2020/11/25 9 | */ 10 | public class DefaultResourceLoader implements ResourceLoader { 11 | 12 | public static final String CLASSPATH_URL_PREFIX = "classpath:"; 13 | 14 | @Override 15 | public Resource getResource(String location) { 16 | if (location.startsWith(CLASSPATH_URL_PREFIX)) { 17 | //classpath下的资源 18 | return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length())); 19 | } else { 20 | try { 21 | //尝试当成url来处理 22 | URL url = new URL(location); 23 | return new UrlResource(url); 24 | } catch (MalformedURLException ex) { 25 | //当成文件系统下的资源处理 26 | return new FileSystemResource(location); 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/core/io/FileSystemResource.java: -------------------------------------------------------------------------------- 1 | package org.springframework.core.io; 2 | 3 | import java.io.File; 4 | import java.io.FileNotFoundException; 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.nio.file.Files; 8 | import java.nio.file.NoSuchFileException; 9 | import java.nio.file.Path; 10 | 11 | /** 12 | * @author derekyi 13 | * @date 2020/11/25 14 | */ 15 | public class FileSystemResource implements Resource { 16 | 17 | private final String filePath; 18 | 19 | public FileSystemResource(String filePath) { 20 | this.filePath = filePath; 21 | } 22 | 23 | @Override 24 | public InputStream getInputStream() throws IOException { 25 | 26 | try { 27 | Path path = new File(this.filePath).toPath(); 28 | return Files.newInputStream(path); 29 | } catch (NoSuchFileException ex) { 30 | throw new FileNotFoundException(ex.getMessage()); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/core/io/Resource.java: -------------------------------------------------------------------------------- 1 | package org.springframework.core.io; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | 6 | /** 7 | * 资源的抽象和访问接口 8 | * 9 | * @author derekyi 10 | * @date 2020/11/25 11 | */ 12 | public interface Resource { 13 | 14 | InputStream getInputStream() throws IOException; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/core/io/ResourceLoader.java: -------------------------------------------------------------------------------- 1 | package org.springframework.core.io; 2 | 3 | /** 4 | * 资源加载器接口 5 | * 6 | * @author derekyi 7 | * @date 2020/11/25 8 | */ 9 | public interface ResourceLoader { 10 | 11 | Resource getResource(String location); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/core/io/UrlResource.java: -------------------------------------------------------------------------------- 1 | package org.springframework.core.io; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.net.URL; 6 | import java.net.URLConnection; 7 | 8 | /** 9 | * @author derekyi 10 | * @date 2020/11/25 11 | */ 12 | public class UrlResource implements Resource { 13 | 14 | private final URL url; 15 | 16 | public UrlResource(URL url) { 17 | this.url = url; 18 | } 19 | 20 | @Override 21 | public InputStream getInputStream() throws IOException { 22 | URLConnection con = this.url.openConnection(); 23 | try { 24 | return con.getInputStream(); 25 | } catch (IOException ex) { 26 | throw ex; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/stereotype/Component.java: -------------------------------------------------------------------------------- 1 | package org.springframework.stereotype; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @author derekyi 7 | * @date 2020/12/26 8 | */ 9 | @Target(ElementType.TYPE) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Documented 12 | public @interface Component { 13 | 14 | String value() default ""; 15 | } -------------------------------------------------------------------------------- /src/main/java/org/springframework/util/StringValueResolver.java: -------------------------------------------------------------------------------- 1 | package org.springframework.util; 2 | 3 | /** 4 | * @author derekyi 5 | * @date 2020/12/27 6 | */ 7 | public interface StringValueResolver { 8 | 9 | String resolveStringValue(String strVal); 10 | } 11 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/aop/AutoProxyTest.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.aop; 2 | 3 | import org.junit.Test; 4 | import org.springframework.context.support.ClassPathXmlApplicationContext; 5 | import org.springframework.test.service.WorldService; 6 | 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | 9 | /** 10 | * @author derekyi 11 | * @date 2020/12/6 12 | */ 13 | public class AutoProxyTest { 14 | 15 | @Test 16 | public void testAutoProxy() throws Exception { 17 | ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:auto-proxy.xml"); 18 | 19 | //获取代理对象 20 | WorldService worldService = applicationContext.getBean("worldService", WorldService.class); 21 | worldService.explode(); 22 | } 23 | 24 | @Test 25 | public void testPopulateProxyBeanWithPropertyValues() throws Exception { 26 | ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:populate-proxy-bean-with-property-values.xml"); 27 | 28 | //获取代理对象 29 | WorldService worldService = applicationContext.getBean("worldService", WorldService.class); 30 | worldService.explode(); 31 | assertThat(worldService.getName()).isEqualTo("earth"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/aop/DynamicProxyTest.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.aop; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | 6 | import org.springframework.aop.AdvisedSupport; 7 | import org.springframework.aop.ClassFilter; 8 | import org.springframework.aop.TargetSource; 9 | import org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor; 10 | import org.springframework.aop.framework.CglibAopProxy; 11 | import org.springframework.aop.framework.JdkDynamicAopProxy; 12 | import org.springframework.aop.framework.ProxyFactory; 13 | import org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor; 14 | import org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor; 15 | import org.springframework.test.common.WorldServiceAfterReturnAdvice; 16 | import org.springframework.test.common.WorldServiceBeforeAdvice; 17 | import org.springframework.test.service.WorldService; 18 | import org.springframework.test.service.WorldServiceImpl; 19 | 20 | /** 21 | * @author derekyi 22 | * @date 2020/12/6 23 | */ 24 | public class DynamicProxyTest { 25 | 26 | private AdvisedSupport advisedSupport; 27 | 28 | @Before 29 | public void setup() { 30 | WorldService worldService = new WorldServiceImpl(); 31 | advisedSupport = new ProxyFactory(); 32 | //Advisor是Pointcut和Advice的组合 33 | String expression = "execution(* org.springframework.test.service.WorldService.explode(..))"; 34 | AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor(); 35 | advisor.setExpression(expression); 36 | AfterReturningAdviceInterceptor methodInterceptor = new AfterReturningAdviceInterceptor(new WorldServiceAfterReturnAdvice()); 37 | advisor.setAdvice(methodInterceptor); 38 | TargetSource targetSource = new TargetSource(worldService); 39 | advisedSupport.setTargetSource(targetSource); 40 | advisedSupport.addAdvisor(advisor); 41 | } 42 | 43 | @Test 44 | public void testJdkDynamicProxy() throws Exception { 45 | WorldService proxy = (WorldService) new JdkDynamicAopProxy(advisedSupport).getProxy(); 46 | proxy.explode(); 47 | } 48 | 49 | @Test 50 | public void testCglibDynamicProxy() throws Exception { 51 | WorldService proxy = (WorldService) new CglibAopProxy(advisedSupport).getProxy(); 52 | proxy.explode(); 53 | } 54 | 55 | @Test 56 | public void testProxyFactory() throws Exception { 57 | // 使用JDK动态代理 58 | ProxyFactory factory = (ProxyFactory) advisedSupport; 59 | factory.setProxyTargetClass(false); 60 | WorldService proxy = (WorldService) factory.getProxy(); 61 | proxy.explode(); 62 | 63 | // 使用CGLIB动态代理 64 | factory.setProxyTargetClass(true); 65 | proxy = (WorldService) factory.getProxy(); 66 | proxy.explode(); 67 | } 68 | 69 | @Test 70 | public void testBeforeAdvice() throws Exception { 71 | //设置BeforeAdvice 72 | String expression = "execution(* org.springframework.test.service.WorldService.explode(..))"; 73 | AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor(); 74 | advisor.setExpression(expression); 75 | MethodBeforeAdviceInterceptor methodInterceptor = new MethodBeforeAdviceInterceptor(new WorldServiceBeforeAdvice()); 76 | advisor.setAdvice(methodInterceptor); 77 | advisedSupport.addAdvisor(advisor); 78 | ProxyFactory factory = (ProxyFactory) advisedSupport; 79 | WorldService proxy = (WorldService) factory.getProxy(); 80 | proxy.explode(); 81 | } 82 | 83 | @Test 84 | public void testAdvisor() throws Exception { 85 | WorldService worldService = new WorldServiceImpl(); 86 | 87 | //Advisor是Pointcut和Advice的组合 88 | String expression = "execution(* org.springframework.test.service.WorldService.explode(..))"; 89 | AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor(); 90 | advisor.setExpression(expression); 91 | MethodBeforeAdviceInterceptor methodInterceptor = new MethodBeforeAdviceInterceptor(new WorldServiceBeforeAdvice()); 92 | advisor.setAdvice(methodInterceptor); 93 | 94 | ClassFilter classFilter = advisor.getPointcut().getClassFilter(); 95 | if (classFilter.matches(worldService.getClass())) { 96 | ProxyFactory proxyFactory = new ProxyFactory(); 97 | 98 | TargetSource targetSource = new TargetSource(worldService); 99 | proxyFactory.setTargetSource(targetSource); 100 | proxyFactory.addAdvisor(advisor); 101 | // proxyFactory.setMethodMatcher(advisor.getPointcut().getMethodMatcher()); 102 | // advisedSupport.setProxyTargetClass(true); //JDK or CGLIB 103 | 104 | WorldService proxy = (WorldService) proxyFactory.getProxy(); 105 | proxy.explode(); 106 | } 107 | } 108 | } 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/aop/PointcutExpressionTest.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.aop; 2 | 3 | import org.junit.Test; 4 | import org.springframework.aop.aspectj.AspectJExpressionPointcut; 5 | import org.springframework.test.service.HelloService; 6 | 7 | import java.lang.reflect.Method; 8 | 9 | import static org.assertj.core.api.Assertions.assertThat; 10 | 11 | /** 12 | * @author derekyi 13 | * @date 2020/12/5 14 | */ 15 | public class PointcutExpressionTest { 16 | 17 | @Test 18 | public void testPointcutExpression() throws Exception { 19 | AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut("execution(* org.springframework.test.service.HelloService.*(..))"); 20 | Class clazz = HelloService.class; 21 | Method method = clazz.getDeclaredMethod("sayHello"); 22 | 23 | assertThat(pointcut.matches(clazz)).isTrue(); 24 | assertThat(pointcut.matches(method, clazz)).isTrue(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/aop/ProxyFactoryTest.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.aop; 2 | 3 | import org.junit.Test; 4 | 5 | import org.springframework.aop.TargetSource; 6 | import org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor; 7 | import org.springframework.aop.framework.ProxyFactory; 8 | import org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor; 9 | import org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor; 10 | import org.springframework.test.common.WorldServiceAfterReturnAdvice; 11 | import org.springframework.test.common.WorldServiceBeforeAdvice; 12 | import org.springframework.test.service.WorldService; 13 | import org.springframework.test.service.WorldServiceImpl; 14 | 15 | public class ProxyFactoryTest { 16 | @Test 17 | public void testAdvisor() throws Exception { 18 | WorldService worldService = new WorldServiceImpl(); 19 | 20 | //Advisor是Pointcut和Advice的组合 21 | String expression = "execution(* org.springframework.test.service.WorldService.explode(..))"; 22 | //第一个切面 23 | AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor(); 24 | advisor.setExpression(expression); 25 | MethodBeforeAdviceInterceptor methodInterceptor = new MethodBeforeAdviceInterceptor(new WorldServiceBeforeAdvice()); 26 | advisor.setAdvice(methodInterceptor); 27 | //第二个切面 28 | AspectJExpressionPointcutAdvisor advisor1 = new AspectJExpressionPointcutAdvisor(); 29 | advisor1.setExpression(expression); 30 | AfterReturningAdviceInterceptor afterReturningAdviceInterceptor = new AfterReturningAdviceInterceptor(new WorldServiceAfterReturnAdvice()); 31 | advisor1.setAdvice(afterReturningAdviceInterceptor); 32 | //通过ProxyFactory来获得代理 33 | ProxyFactory factory = new ProxyFactory(); 34 | TargetSource targetSource = new TargetSource(worldService); 35 | factory.setTargetSource(targetSource); 36 | factory.setProxyTargetClass(true); 37 | factory.addAdvisor(advisor); 38 | factory.addAdvisor(advisor1); 39 | WorldService proxy = (WorldService) factory.getProxy(); 40 | proxy.explode(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/bean/A.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.bean; 2 | 3 | /** 4 | * @author derekyi 5 | * @date 2021/1/25 6 | */ 7 | public class A { 8 | 9 | private B b; 10 | 11 | public void func(){} 12 | 13 | public B getB() { 14 | return b; 15 | } 16 | 17 | public void setB(B b) { 18 | this.b = b; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/bean/B.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.bean; 2 | 3 | /** 4 | * @author derekyi 5 | * @date 2021/1/25 6 | */ 7 | public class B { 8 | 9 | private A a; 10 | 11 | public A getA() { 12 | return a; 13 | } 14 | 15 | public void setA(A a) { 16 | this.a = a; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/bean/Car.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.bean; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.stereotype.Component; 5 | 6 | import java.text.SimpleDateFormat; 7 | import java.time.LocalDate; 8 | 9 | /** 10 | * @author derekyi 11 | * @date 2020/11/24 12 | */ 13 | @Component 14 | public class Car { 15 | 16 | private int price; 17 | 18 | private LocalDate produceDate; 19 | 20 | private long date; 21 | 22 | @Value("${brand}") 23 | private String brand; 24 | 25 | public String getBrand() { 26 | return brand; 27 | } 28 | 29 | public void setBrand(String brand) { 30 | this.brand = brand; 31 | } 32 | 33 | public int getPrice() { 34 | return price; 35 | } 36 | 37 | public void setPrice(int price) { 38 | this.price = price; 39 | } 40 | 41 | public LocalDate getProduceDate() { 42 | return produceDate; 43 | } 44 | 45 | public void setProduceDate(LocalDate produceDate) { 46 | this.produceDate = produceDate; 47 | } 48 | 49 | public void init() { 50 | date = System.currentTimeMillis(); 51 | } 52 | 53 | public void showTime() { 54 | SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd :hh:mm:ss"); 55 | System.out.println(date + ":bean create"); 56 | } 57 | 58 | @Override 59 | public String toString() { 60 | return "Car{" + 61 | "price=" + price + 62 | ", produceDate=" + produceDate + 63 | ", brand='" + brand + '\'' + 64 | '}'; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/bean/Person.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.bean; 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.stereotype.Component; 7 | 8 | /** 9 | * @author derekyi 10 | * @date 2020/11/24 11 | */ 12 | @Component 13 | public class Person implements InitializingBean, DisposableBean { 14 | 15 | private String name; 16 | 17 | private int age; 18 | 19 | @Autowired 20 | private Car car; 21 | 22 | public void customInitMethod() { 23 | System.out.println("I was born in the method named customInitMethod"); 24 | } 25 | 26 | public void customDestroyMethod() { 27 | System.out.println("I died in the method named customDestroyMethod"); 28 | } 29 | 30 | @Override 31 | public void afterPropertiesSet() throws Exception { 32 | System.out.println("I was born in the method named afterPropertiesSet"); 33 | } 34 | 35 | @Override 36 | public void destroy() throws Exception { 37 | System.out.println("I died in the method named destroy"); 38 | } 39 | 40 | public String getName() { 41 | return name; 42 | } 43 | 44 | public void setName(String name) { 45 | this.name = name; 46 | } 47 | 48 | public int getAge() { 49 | return age; 50 | } 51 | 52 | public void setAge(int age) { 53 | this.age = age; 54 | } 55 | 56 | public Car getCar() { 57 | return car; 58 | } 59 | 60 | public void setCar(Car car) { 61 | this.car = car; 62 | } 63 | 64 | @Override 65 | public String toString() { 66 | return "Person{" + 67 | "name='" + name + '\'' + 68 | ", age=" + age + 69 | ", car=" + car + 70 | '}'; 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/common/ABeforeAdvice.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.common; 2 | 3 | import org.springframework.aop.MethodBeforeAdvice; 4 | 5 | import java.lang.reflect.Method; 6 | 7 | /** 8 | * @author derekyi 9 | * @date 2021/1/30 10 | */ 11 | public class ABeforeAdvice implements MethodBeforeAdvice { 12 | @Override 13 | public void before(Method method, Object[] args, Object target) throws Throwable { 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/common/CarFactoryBean.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.common; 2 | 3 | import org.springframework.beans.factory.FactoryBean; 4 | import org.springframework.test.bean.Car; 5 | 6 | /** 7 | * @author derekyi 8 | * @date 2020/12/2 9 | */ 10 | public class CarFactoryBean implements FactoryBean { 11 | 12 | private String brand; 13 | 14 | @Override 15 | public Car getObject() throws Exception { 16 | Car car = new Car(); 17 | car.setBrand(brand); 18 | return car; 19 | } 20 | 21 | @Override 22 | public boolean isSingleton() { 23 | return true; 24 | } 25 | 26 | public void setBrand(String brand) { 27 | this.brand = brand; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/common/ConvertersFactoryBean.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.common; 2 | 3 | import org.springframework.beans.factory.FactoryBean; 4 | 5 | import java.util.HashSet; 6 | import java.util.Set; 7 | 8 | /** 9 | * @author derekyi 10 | * @date 2021/1/17 11 | */ 12 | public class ConvertersFactoryBean implements FactoryBean> { 13 | 14 | @Override 15 | public Set getObject() throws Exception { 16 | HashSet converters = new HashSet<>(); 17 | StringToLocalDateConverter stringToLocalDateConverter = new StringToLocalDateConverter("yyyy-MM-dd"); 18 | converters.add(stringToLocalDateConverter); 19 | return converters; 20 | } 21 | 22 | @Override 23 | public boolean isSingleton() { 24 | return true; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/common/CustomBeanFactoryPostProcessor.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.common; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.PropertyValue; 5 | import org.springframework.beans.PropertyValues; 6 | import org.springframework.beans.factory.ConfigurableListableBeanFactory; 7 | import org.springframework.beans.factory.config.BeanDefinition; 8 | import org.springframework.beans.factory.config.BeanFactoryPostProcessor; 9 | 10 | /** 11 | * @author derekyi 12 | * @date 2020/11/28 13 | */ 14 | public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor { 15 | 16 | @Override 17 | public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { 18 | System.out.println("CustomBeanFactoryPostProcessor#postProcessBeanFactory"); 19 | BeanDefinition personBeanDefiniton = beanFactory.getBeanDefinition("person"); 20 | PropertyValues propertyValues = personBeanDefiniton.getPropertyValues(); 21 | //将person的name属性改为ivy 22 | propertyValues.addPropertyValue(new PropertyValue("name", "ivy")); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/common/CustomerBeanPostProcessor.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.common; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.factory.config.BeanPostProcessor; 5 | import org.springframework.test.bean.Car; 6 | 7 | /** 8 | * @author derekyi 9 | * @date 2020/11/28 10 | */ 11 | public class CustomerBeanPostProcessor implements BeanPostProcessor { 12 | @Override 13 | public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 14 | System.out.println("CustomerBeanPostProcessor#postProcessBeforeInitialization, beanName: " + beanName); 15 | //换兰博基尼 16 | if ("car".equals(beanName)) { 17 | ((Car) bean).setBrand("lamborghini"); 18 | } 19 | return bean; 20 | } 21 | 22 | @Override 23 | public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 24 | System.out.println("CustomerBeanPostProcessor#postProcessAfterInitialization, beanName: " + beanName); 25 | return bean; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/common/StringToBooleanConverter.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.common; 2 | 3 | import org.springframework.core.convert.converter.GenericConverter; 4 | 5 | import java.util.Collections; 6 | import java.util.Set; 7 | 8 | /** 9 | * @author derekyi 10 | * @date 2021/1/16 11 | */ 12 | public class StringToBooleanConverter implements GenericConverter { 13 | @Override 14 | public Set getConvertibleTypes() { 15 | return Collections.singleton(new ConvertiblePair(String.class, Boolean.class)); 16 | } 17 | 18 | @Override 19 | public Object convert(Object source, Class sourceType, Class targetType) { 20 | return Boolean.valueOf((String) source); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/common/StringToIntegerConverter.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.common; 2 | 3 | import org.springframework.core.convert.converter.Converter; 4 | 5 | /** 6 | * @author derekyi 7 | * @date 2021/1/16 8 | */ 9 | public class StringToIntegerConverter implements Converter { 10 | @Override 11 | public Integer convert(String source) { 12 | return Integer.valueOf(source); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/common/StringToLocalDateConverter.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.common; 2 | 3 | import org.springframework.core.convert.converter.Converter; 4 | 5 | import java.time.LocalDate; 6 | import java.time.format.DateTimeFormatter; 7 | 8 | /** 9 | * @author derekyi 10 | * @date 2021/1/17 11 | */ 12 | public class StringToLocalDateConverter implements Converter { 13 | 14 | private final DateTimeFormatter DATE_TIME_FORMATTER; 15 | 16 | public StringToLocalDateConverter(String pattern) { 17 | DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern(pattern); 18 | } 19 | 20 | @Override 21 | public LocalDate convert(String source) { 22 | return LocalDate.parse(source, DATE_TIME_FORMATTER); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/common/WorldServiceAfterReturnAdvice.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.common; 2 | 3 | import org.springframework.aop.AfterReturningAdvice; 4 | 5 | import java.lang.reflect.Method; 6 | 7 | public class WorldServiceAfterReturnAdvice implements AfterReturningAdvice { 8 | 9 | @Override 10 | public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { 11 | System.out.println("AfterAdvice: do something after the earth explodes"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/common/WorldServiceBeforeAdvice.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.common; 2 | 3 | import org.springframework.aop.MethodBeforeAdvice; 4 | 5 | import java.lang.reflect.Method; 6 | 7 | /** 8 | * @author derekyi 9 | * @date 2020/12/6 10 | */ 11 | public class WorldServiceBeforeAdvice implements MethodBeforeAdvice { 12 | 13 | @Override 14 | public void before(Method method, Object[] args, Object target) throws Throwable { 15 | System.out.println("BeforeAdvice: do something before the earth explodes"); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/common/WorldServiceInterceptor.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.common; 2 | 3 | import org.aopalliance.intercept.MethodInterceptor; 4 | import org.aopalliance.intercept.MethodInvocation; 5 | 6 | /** 7 | * @author derekyi 8 | * @date 2020/12/6 9 | */ 10 | public class WorldServiceInterceptor implements MethodInterceptor { 11 | @Override 12 | public Object invoke(MethodInvocation invocation) throws Throwable { 13 | System.out.println("Do something before the earth explodes"); 14 | Object result = invocation.proceed(); 15 | System.out.println("Do something after the earth explodes"); 16 | return result; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/common/event/ContextClosedEventListener.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.common.event; 2 | 3 | import org.springframework.context.ApplicationListener; 4 | import org.springframework.context.event.ContextClosedEvent; 5 | 6 | /** 7 | * @author derekyi 8 | * @date 2020/12/5 9 | */ 10 | public class ContextClosedEventListener implements ApplicationListener { 11 | @Override 12 | public void onApplicationEvent(ContextClosedEvent event) { 13 | System.out.println(this.getClass().getName()); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/common/event/ContextRefreshedEventListener.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.common.event; 2 | 3 | import org.springframework.context.ApplicationListener; 4 | import org.springframework.context.event.ContextRefreshedEvent; 5 | 6 | /** 7 | * @author derekyi 8 | * @date 2020/12/5 9 | */ 10 | public class ContextRefreshedEventListener implements ApplicationListener { 11 | 12 | @Override 13 | public void onApplicationEvent(ContextRefreshedEvent event) { 14 | System.out.println(this.getClass().getName()); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/common/event/CustomEvent.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.common.event; 2 | 3 | import org.springframework.context.ApplicationContext; 4 | import org.springframework.context.event.ApplicationContextEvent; 5 | 6 | /** 7 | * @author derekyi 8 | * @date 2020/12/5 9 | */ 10 | public class CustomEvent extends ApplicationContextEvent { 11 | 12 | public CustomEvent(ApplicationContext source) { 13 | super(source); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/common/event/CustomEventListener.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.common.event; 2 | 3 | import org.springframework.context.ApplicationListener; 4 | 5 | /** 6 | * @author derekyi 7 | * @date 2020/12/5 8 | */ 9 | public class CustomEventListener implements ApplicationListener { 10 | 11 | @Override 12 | public void onApplicationEvent(CustomEvent event) { 13 | System.out.println(this.getClass().getName()); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/expanding/PropertyPlaceholderConfigurerTest.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.expanding; 2 | 3 | import org.junit.Test; 4 | import org.springframework.context.support.ClassPathXmlApplicationContext; 5 | import org.springframework.test.bean.Car; 6 | 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | 9 | /** 10 | * @author derekyi 11 | * @date 2020/12/13 12 | */ 13 | public class PropertyPlaceholderConfigurerTest { 14 | 15 | @Test 16 | public void test() throws Exception { 17 | ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:property-placeholder-configurer.xml"); 18 | 19 | Car car = applicationContext.getBean("car", Car.class); 20 | assertThat(car.getBrand()).isEqualTo("lamborghini"); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/ioc/ApplicationContextTest.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.ioc; 2 | 3 | import org.junit.Test; 4 | import org.springframework.context.support.ClassPathXmlApplicationContext; 5 | import org.springframework.test.bean.Car; 6 | import org.springframework.test.bean.Person; 7 | 8 | import static org.assertj.core.api.Assertions.assertThat; 9 | 10 | /** 11 | * @author derekyi 12 | * @date 2020/11/28 13 | */ 14 | public class ApplicationContextTest { 15 | 16 | @Test 17 | public void testApplicationContext() throws Exception { 18 | ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml"); 19 | 20 | Person person = applicationContext.getBean("person", Person.class); 21 | System.out.println(person); 22 | //name属性在CustomBeanFactoryPostProcessor中被修改为ivy 23 | assertThat(person.getName()).isEqualTo("ivy"); 24 | 25 | Car car = applicationContext.getBean("car", Car.class); 26 | System.out.println(car); 27 | //brand属性在CustomerBeanPostProcessor中被修改为lamborghini 28 | assertThat(car.getBrand()).isEqualTo("lamborghini"); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/ioc/AutowiredAnnotationTest.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.ioc; 2 | 3 | import org.junit.Test; 4 | import org.springframework.context.support.ClassPathXmlApplicationContext; 5 | import org.springframework.test.bean.Person; 6 | 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | 9 | /** 10 | * @author derekyi 11 | * @date 2020/12/27 12 | */ 13 | public class AutowiredAnnotationTest { 14 | 15 | @Test 16 | public void testAutowiredAnnotation() throws Exception { 17 | ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:autowired-annotation.xml"); 18 | 19 | Person person = applicationContext.getBean(Person.class); 20 | assertThat(person.getCar()).isNotNull(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/ioc/AwareInterfaceTest.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.ioc; 2 | 3 | import org.junit.Test; 4 | import org.springframework.context.support.ClassPathXmlApplicationContext; 5 | import org.springframework.test.service.HelloService; 6 | 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | 9 | /** 10 | * @author derekyi 11 | * @date 2020/12/1 12 | */ 13 | public class AwareInterfaceTest { 14 | 15 | @Test 16 | public void test() throws Exception { 17 | ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml"); 18 | HelloService helloService = applicationContext.getBean("helloService", HelloService.class); 19 | assertThat(helloService.getApplicationContext()).isNotNull(); 20 | assertThat(helloService.getBeanFactory()).isNotNull(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/ioc/BeanDefinitionAndBeanDefinitionRegistryTest.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.ioc; 2 | 3 | import org.junit.Test; 4 | import org.springframework.beans.factory.config.BeanDefinition; 5 | import org.springframework.beans.factory.support.DefaultListableBeanFactory; 6 | import org.springframework.test.service.HelloService; 7 | 8 | /** 9 | * @author derekyi 10 | * @date 2020/11/24 11 | */ 12 | public class BeanDefinitionAndBeanDefinitionRegistryTest { 13 | 14 | @Test 15 | public void testBeanFactory() throws Exception { 16 | DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); 17 | BeanDefinition beanDefinition = new BeanDefinition(HelloService.class); 18 | beanFactory.registerBeanDefinition("helloService", beanDefinition); 19 | 20 | HelloService helloService = (HelloService) beanFactory.getBean("helloService"); 21 | helloService.sayHello(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/ioc/BeanFactoryPostProcessorAndBeanPostProcessorTest.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.ioc; 2 | 3 | import org.junit.Test; 4 | import org.springframework.beans.factory.support.DefaultListableBeanFactory; 5 | import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; 6 | import org.springframework.test.bean.Car; 7 | import org.springframework.test.bean.Person; 8 | import org.springframework.test.common.CustomBeanFactoryPostProcessor; 9 | import org.springframework.test.common.CustomerBeanPostProcessor; 10 | 11 | import static org.assertj.core.api.Assertions.assertThat; 12 | 13 | /** 14 | * @author derekyi 15 | * @date 2020/11/28 16 | */ 17 | public class BeanFactoryPostProcessorAndBeanPostProcessorTest { 18 | 19 | @Test 20 | public void testBeanFactoryPostProcessor() throws Exception { 21 | DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); 22 | XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); 23 | beanDefinitionReader.loadBeanDefinitions("classpath:spring.xml"); 24 | 25 | //在所有BeanDefintion加载完成后,但在bean实例化之前,修改BeanDefinition的属性值 26 | CustomBeanFactoryPostProcessor beanFactoryPostProcessor = new CustomBeanFactoryPostProcessor(); 27 | beanFactoryPostProcessor.postProcessBeanFactory(beanFactory); 28 | 29 | Person person = (Person) beanFactory.getBean("person"); 30 | System.out.println(person); 31 | //name属性在CustomBeanFactoryPostProcessor中被修改为ivy 32 | assertThat(person.getName()).isEqualTo("ivy"); 33 | } 34 | 35 | @Test 36 | public void testBeanPostProcessor() throws Exception { 37 | DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); 38 | XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); 39 | beanDefinitionReader.loadBeanDefinitions("classpath:spring.xml"); 40 | 41 | //添加bean实例化后的处理器 42 | CustomerBeanPostProcessor customerBeanPostProcessor = new CustomerBeanPostProcessor(); 43 | beanFactory.addBeanPostProcessor(customerBeanPostProcessor); 44 | 45 | Car car = (Car) beanFactory.getBean("car"); 46 | System.out.println(car); 47 | //brand属性在CustomerBeanPostProcessor中被修改为lamborghini 48 | assertThat(car.getBrand()).isEqualTo("lamborghini"); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/ioc/CircularReferenceWithProxyBeanTest.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.ioc; 2 | 3 | import org.junit.Test; 4 | import org.springframework.context.support.ClassPathXmlApplicationContext; 5 | import org.springframework.test.bean.A; 6 | import org.springframework.test.bean.B; 7 | 8 | import static org.assertj.core.api.Java6Assertions.assertThat; 9 | 10 | /** 11 | * @author derekyi 12 | * @date 2021/1/30 13 | */ 14 | public class CircularReferenceWithProxyBeanTest { 15 | 16 | @Test 17 | public void testCircularReference() throws Exception { 18 | ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:circular-reference-with-proxy-bean.xml"); 19 | A a = applicationContext.getBean("a", A.class); 20 | B b = applicationContext.getBean("b", B.class); 21 | 22 | assertThat(b.getA() == a).isTrue(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/ioc/CircularReferenceWithoutProxyBeanTest.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.ioc; 2 | 3 | import org.junit.Test; 4 | import org.springframework.context.support.ClassPathXmlApplicationContext; 5 | import org.springframework.test.bean.A; 6 | import org.springframework.test.bean.B; 7 | 8 | import static org.assertj.core.api.Java6Assertions.assertThat; 9 | 10 | /** 11 | * @author derekyi 12 | * @date 2021/1/25 13 | */ 14 | public class CircularReferenceWithoutProxyBeanTest { 15 | 16 | @Test 17 | public void testCircularReference() throws Exception { 18 | ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:circular-reference-without-proxy-bean.xml"); 19 | A a = applicationContext.getBean("a", A.class); 20 | B b = applicationContext.getBean("b", B.class); 21 | assertThat(a.getB() == b).isTrue(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/ioc/EventAndEventListenerTest.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.ioc; 2 | 3 | import org.junit.Test; 4 | import org.springframework.context.support.ClassPathXmlApplicationContext; 5 | import org.springframework.test.common.event.CustomEvent; 6 | 7 | /** 8 | * @author derekyi 9 | * @date 2020/12/5 10 | */ 11 | public class EventAndEventListenerTest { 12 | 13 | @Test 14 | public void testEventListener() throws Exception { 15 | ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:event-and-event-listener.xml"); 16 | applicationContext.publishEvent(new CustomEvent(applicationContext)); 17 | 18 | applicationContext.registerShutdownHook();//或者applicationContext.close()主动关闭容器; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/ioc/FactoryBeanTest.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.ioc; 2 | 3 | import org.junit.Test; 4 | import org.springframework.context.support.ClassPathXmlApplicationContext; 5 | import org.springframework.test.bean.Car; 6 | 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | 9 | /** 10 | * @author derekyi 11 | * @date 2020/12/2 12 | */ 13 | public class FactoryBeanTest { 14 | 15 | @Test 16 | public void testFactoryBean() throws Exception { 17 | ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:factory-bean.xml"); 18 | 19 | Car car = applicationContext.getBean("car", Car.class); 20 | assertThat(car.getBrand()).isEqualTo("porsche"); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/ioc/HelloService.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.ioc; 2 | 3 | /** 4 | * @author derekyi 5 | * @date 2020/11/22 6 | */ 7 | public class HelloService { 8 | 9 | public String sayHello() { 10 | System.out.println("hello"); 11 | return "hello"; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/ioc/InitAndDestoryMethodTest.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.ioc; 2 | 3 | import org.junit.Test; 4 | import org.springframework.context.support.ClassPathXmlApplicationContext; 5 | 6 | /** 7 | * @author derekyi 8 | * @date 2020/11/29 9 | */ 10 | public class InitAndDestoryMethodTest { 11 | 12 | @Test 13 | public void testInitAndDestroyMethod() throws Exception { 14 | ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:init-and-destroy-method.xml"); 15 | applicationContext.registerShutdownHook(); //或者手动关闭 applicationContext.close(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/ioc/LazyInitTest.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.ioc; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | import org.junit.Test; 6 | 7 | import org.springframework.context.support.ClassPathXmlApplicationContext; 8 | import org.springframework.test.bean.Car; 9 | 10 | public class LazyInitTest { 11 | 12 | @Test 13 | public void testLazyInit() throws InterruptedException { 14 | ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:lazy-test.xml"); 15 | System.out.println(System.currentTimeMillis() + ":applicationContext-over"); 16 | TimeUnit.SECONDS.sleep(1); 17 | Car c = (Car) applicationContext.getBean("car"); 18 | c.showTime();//显示bean的创建时间 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/ioc/PackageScanTest.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.ioc; 2 | 3 | import org.junit.Test; 4 | import org.springframework.context.support.ClassPathXmlApplicationContext; 5 | import org.springframework.test.bean.Car; 6 | 7 | import static org.assertj.core.api.Java6Assertions.assertThat; 8 | 9 | /** 10 | * @author derekyi 11 | * @date 2020/12/26 12 | */ 13 | public class PackageScanTest { 14 | 15 | @Test 16 | public void testScanPackage() throws Exception { 17 | ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:package-scan.xml"); 18 | 19 | Car car = applicationContext.getBean("car", Car.class); 20 | assertThat(car).isNotNull(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/ioc/PopulateBeanWithPropertyValuesTest.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.ioc; 2 | 3 | import org.junit.Test; 4 | import org.springframework.beans.PropertyValue; 5 | import org.springframework.beans.PropertyValues; 6 | import org.springframework.beans.factory.config.BeanReference; 7 | import org.springframework.test.bean.Car; 8 | import org.springframework.test.bean.Person; 9 | import org.springframework.beans.factory.config.BeanDefinition; 10 | import org.springframework.beans.factory.support.DefaultListableBeanFactory; 11 | 12 | import static org.assertj.core.api.Assertions.assertThat; 13 | 14 | /** 15 | * @author derekyi 16 | * @date 2020/11/24 17 | */ 18 | public class PopulateBeanWithPropertyValuesTest { 19 | 20 | @Test 21 | public void testPopulateBeanWithPropertyValues() throws Exception { 22 | DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); 23 | PropertyValues propertyValues = new PropertyValues(); 24 | propertyValues.addPropertyValue(new PropertyValue("name", "derek")); 25 | propertyValues.addPropertyValue(new PropertyValue("age", 18)); 26 | BeanDefinition beanDefinition = new BeanDefinition(Person.class, propertyValues); 27 | beanFactory.registerBeanDefinition("person", beanDefinition); 28 | 29 | Person person = (Person) beanFactory.getBean("person"); 30 | System.out.println(person); 31 | assertThat(person.getName()).isEqualTo("derek"); 32 | assertThat(person.getAge()).isEqualTo(18); 33 | } 34 | 35 | /** 36 | * 为bean注入bean 37 | * 38 | * @throws Exception 39 | */ 40 | @Test 41 | public void testPopulateBeanWithBean() throws Exception { 42 | DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); 43 | 44 | //注册Car实例 45 | PropertyValues propertyValuesForCar = new PropertyValues(); 46 | propertyValuesForCar.addPropertyValue(new PropertyValue("brand", "porsche")); 47 | BeanDefinition carBeanDefinition = new BeanDefinition(Car.class, propertyValuesForCar); 48 | beanFactory.registerBeanDefinition("car", carBeanDefinition); 49 | 50 | //注册Person实例 51 | PropertyValues propertyValuesForPerson = new PropertyValues(); 52 | propertyValuesForPerson.addPropertyValue(new PropertyValue("name", "derek")); 53 | propertyValuesForPerson.addPropertyValue(new PropertyValue("age", 18)); 54 | //Person实例依赖Car实例 55 | propertyValuesForPerson.addPropertyValue(new PropertyValue("car", new BeanReference("car"))); 56 | BeanDefinition beanDefinition = new BeanDefinition(Person.class, propertyValuesForPerson); 57 | beanFactory.registerBeanDefinition("person", beanDefinition); 58 | 59 | Person person = (Person) beanFactory.getBean("person"); 60 | System.out.println(person); 61 | assertThat(person.getName()).isEqualTo("derek"); 62 | assertThat(person.getAge()).isEqualTo(18); 63 | Car car = person.getCar(); 64 | assertThat(car).isNotNull(); 65 | assertThat(car.getBrand()).isEqualTo("porsche"); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/ioc/PrototypeBeanTest.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.ioc; 2 | 3 | import org.junit.Test; 4 | import org.springframework.context.support.ClassPathXmlApplicationContext; 5 | import org.springframework.test.bean.Car; 6 | 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | 9 | /** 10 | * @author derekyi 11 | * @date 2020/12/2 12 | */ 13 | public class PrototypeBeanTest { 14 | 15 | @Test 16 | public void testPrototype() throws Exception { 17 | ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:prototype-bean.xml"); 18 | 19 | Car car1 = applicationContext.getBean("car", Car.class); 20 | Car car2 = applicationContext.getBean("car", Car.class); 21 | assertThat(car1 != car2).isTrue(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/ioc/ResourceAndResourceLoaderTest.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.ioc; 2 | 3 | import cn.hutool.core.io.IoUtil; 4 | import org.junit.Test; 5 | import org.springframework.core.io.*; 6 | 7 | import java.io.InputStream; 8 | 9 | import static org.assertj.core.api.Assertions.assertThat; 10 | 11 | /** 12 | * @author derekyi 13 | * @date 2020/11/25 14 | */ 15 | public class ResourceAndResourceLoaderTest { 16 | 17 | @Test 18 | public void testResourceLoader() throws Exception { 19 | DefaultResourceLoader resourceLoader = new DefaultResourceLoader(); 20 | 21 | //加载classpath下的资源 22 | Resource resource = resourceLoader.getResource("classpath:hello.txt"); 23 | InputStream inputStream = resource.getInputStream(); 24 | String content = IoUtil.readUtf8(inputStream); 25 | System.out.println(content); 26 | assertThat(content).isEqualTo("hello world"); 27 | 28 | //加载文件系统资源 29 | resource = resourceLoader.getResource("src/test/resources/hello.txt"); 30 | assertThat(resource instanceof FileSystemResource).isTrue(); 31 | inputStream = resource.getInputStream(); 32 | content = IoUtil.readUtf8(inputStream); 33 | System.out.println(content); 34 | assertThat(content).isEqualTo("hello world"); 35 | 36 | //加载url资源 37 | resource = resourceLoader.getResource("https://github.com/DerekYRC/mini-spring/blob/main/README.md"); 38 | assertThat(resource instanceof UrlResource).isTrue(); 39 | inputStream = resource.getInputStream(); 40 | content = IoUtil.readUtf8(inputStream); 41 | System.out.println(content); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/ioc/TypeConversionFirstPartTest.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.ioc; 2 | 3 | import org.junit.Test; 4 | import org.springframework.core.convert.converter.Converter; 5 | import org.springframework.core.convert.support.GenericConversionService; 6 | import org.springframework.core.convert.support.StringToNumberConverterFactory; 7 | import org.springframework.test.common.StringToBooleanConverter; 8 | import org.springframework.test.common.StringToIntegerConverter; 9 | 10 | import static org.assertj.core.api.Assertions.assertThat; 11 | 12 | 13 | /** 14 | * @author derekyi 15 | * @date 2021/1/16 16 | */ 17 | public class TypeConversionFirstPartTest { 18 | 19 | @Test 20 | public void testStringToIntegerConverter() throws Exception { 21 | StringToIntegerConverter converter = new StringToIntegerConverter(); 22 | Integer num = converter.convert("8888"); 23 | assertThat(num).isEqualTo(8888); 24 | } 25 | 26 | @Test 27 | public void testStringToNumberConverterFactory() throws Exception { 28 | StringToNumberConverterFactory converterFactory = new StringToNumberConverterFactory(); 29 | 30 | Converter stringToIntegerConverter = converterFactory.getConverter(Integer.class); 31 | Integer intNum = stringToIntegerConverter.convert("8888"); 32 | assertThat(intNum).isEqualTo(8888); 33 | 34 | Converter stringToLongConverter = converterFactory.getConverter(Long.class); 35 | Long longNum = stringToLongConverter.convert("8888"); 36 | assertThat(longNum).isEqualTo(8888L); 37 | } 38 | 39 | @Test 40 | public void testGenericConverter() throws Exception { 41 | StringToBooleanConverter converter = new StringToBooleanConverter(); 42 | 43 | Boolean flag = (Boolean) converter.convert("true", String.class, Boolean.class); 44 | assertThat(flag).isTrue(); 45 | } 46 | 47 | @Test 48 | public void testGenericConversionService() throws Exception { 49 | GenericConversionService conversionService = new GenericConversionService(); 50 | conversionService.addConverter(new StringToIntegerConverter()); 51 | 52 | Integer intNum = conversionService.convert("8888", Integer.class); 53 | assertThat(conversionService.canConvert(String.class, Integer.class)).isTrue(); 54 | assertThat(intNum).isEqualTo(8888); 55 | 56 | conversionService.addConverterFactory(new StringToNumberConverterFactory()); 57 | assertThat(conversionService.canConvert(String.class, Long.class)).isTrue(); 58 | Long longNum = conversionService.convert("8888", Long.class); 59 | assertThat(longNum).isEqualTo(8888L); 60 | 61 | conversionService.addConverter(new StringToBooleanConverter()); 62 | assertThat(conversionService.canConvert(String.class, Boolean.class)).isTrue(); 63 | Boolean flag = conversionService.convert("true", Boolean.class); 64 | assertThat(flag).isTrue(); 65 | } 66 | } -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/ioc/TypeConversionSecondPartTest.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.ioc; 2 | 3 | import org.junit.Test; 4 | import org.springframework.context.support.ClassPathXmlApplicationContext; 5 | import org.springframework.test.bean.Car; 6 | 7 | import java.time.LocalDate; 8 | 9 | import static org.assertj.core.api.Assertions.assertThat; 10 | 11 | /** 12 | * @author derekyi 13 | * @date 2021/1/17 14 | */ 15 | public class TypeConversionSecondPartTest { 16 | 17 | @Test 18 | public void testConversionService() throws Exception { 19 | ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:type-conversion-second-part.xml"); 20 | 21 | Car car = applicationContext.getBean("car", Car.class); 22 | assertThat(car.getPrice()).isEqualTo(1000000); 23 | assertThat(car.getProduceDate()).isEqualTo(LocalDate.of(2021, 1, 1)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/ioc/ValueAnnotationTest.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.ioc; 2 | 3 | import org.junit.Test; 4 | import org.springframework.context.support.ClassPathXmlApplicationContext; 5 | import org.springframework.test.bean.Car; 6 | 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | 9 | /** 10 | * @author derekyi 11 | * @date 2020/12/27 12 | */ 13 | public class ValueAnnotationTest { 14 | 15 | @Test 16 | public void testValueAnnotation() throws Exception { 17 | ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:value-annotation.xml"); 18 | 19 | Car car = applicationContext.getBean("car", Car.class); 20 | assertThat(car.getBrand()).isEqualTo("lamborghini"); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/ioc/XmlFileDefineBeanTest.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.ioc; 2 | 3 | import org.junit.Test; 4 | import org.springframework.beans.factory.support.DefaultListableBeanFactory; 5 | import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; 6 | import org.springframework.test.bean.Car; 7 | import org.springframework.test.bean.Person; 8 | 9 | import static org.assertj.core.api.Assertions.assertThat; 10 | 11 | /** 12 | * @author derekyi 13 | * @date 2020/11/26 14 | */ 15 | public class XmlFileDefineBeanTest { 16 | 17 | @Test 18 | public void testXmlFile() throws Exception { 19 | DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); 20 | XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); 21 | beanDefinitionReader.loadBeanDefinitions("classpath:spring.xml"); 22 | 23 | Person person = (Person) beanFactory.getBean("person"); 24 | System.out.println(person); 25 | assertThat(person.getName()).isEqualTo("derek"); 26 | assertThat(person.getCar().getBrand()).isEqualTo("porsche"); 27 | 28 | Car car = (Car) beanFactory.getBean("car"); 29 | System.out.println(car); 30 | assertThat(car.getBrand()).isEqualTo("porsche"); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/service/HelloService.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.service; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.factory.BeanFactory; 5 | import org.springframework.beans.factory.BeanFactoryAware; 6 | import org.springframework.context.ApplicationContext; 7 | import org.springframework.context.ApplicationContextAware; 8 | 9 | /** 10 | * @author derekyi 11 | * @date 2020/11/22 12 | */ 13 | public class HelloService implements ApplicationContextAware, BeanFactoryAware { 14 | 15 | private ApplicationContext applicationContext; 16 | 17 | private BeanFactory beanFactory; 18 | 19 | public String sayHello() { 20 | System.out.println("hello"); 21 | return "hello"; 22 | } 23 | 24 | @Override 25 | public void setBeanFactory(BeanFactory beanFactory) throws BeansException { 26 | this.beanFactory = beanFactory; 27 | } 28 | 29 | @Override 30 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 31 | this.applicationContext = applicationContext; 32 | } 33 | 34 | public ApplicationContext getApplicationContext() { 35 | return applicationContext; 36 | } 37 | 38 | public BeanFactory getBeanFactory() { 39 | return beanFactory; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/service/WorldService.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.service; 2 | 3 | /** 4 | * @author derekyi 5 | * @date 2020/12/6 6 | */ 7 | public interface WorldService { 8 | 9 | void explode(); 10 | 11 | String getName(); 12 | } 13 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/test/service/WorldServiceImpl.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.service; 2 | 3 | /** 4 | * @author derekyi 5 | * @date 2020/12/6 6 | */ 7 | public class WorldServiceImpl implements WorldService { 8 | 9 | private String name; 10 | 11 | @Override 12 | public void explode() { 13 | System.out.println("The " + name + " is going to explode"); 14 | } 15 | 16 | @Override 17 | public String getName() { 18 | return name; 19 | } 20 | 21 | public void setName(String name) { 22 | this.name = name; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/test/resources/auto-proxy.xml: -------------------------------------------------------------------------------- 1 | 2 | 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 | -------------------------------------------------------------------------------- /src/test/resources/autowired-annotation.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/test/resources/car.properties: -------------------------------------------------------------------------------- 1 | brand=lamborghini -------------------------------------------------------------------------------- /src/test/resources/circular-reference-with-proxy-bean.xml: -------------------------------------------------------------------------------- 1 | 2 | 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 | -------------------------------------------------------------------------------- /src/test/resources/circular-reference-without-proxy-bean.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/test/resources/event-and-event-listener.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/test/resources/factory-bean.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/test/resources/hello.txt: -------------------------------------------------------------------------------- 1 | hello world -------------------------------------------------------------------------------- /src/test/resources/init-and-destroy-method.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/test/resources/lazy-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/test/resources/package-scan.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/test/resources/populate-proxy-bean-with-property-values.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/test/resources/property-placeholder-configurer.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/test/resources/prototype-bean.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/test/resources/spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/test/resources/type-conversion-second-part.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/test/resources/value-annotation.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | --------------------------------------------------------------------------------