{"id":1294,"date":"2025-08-14T15:11:09","date_gmt":"2025-08-14T07:11:09","guid":{"rendered":"http:\/\/www.cmd137blog.top\/?p=1294"},"modified":"2025-08-21T15:42:18","modified_gmt":"2025-08-21T07:42:18","slug":"mini-spring-%e4%bb%a3%e7%90%86%e7%af%87-aop%ef%bc%9astep-13%ef%bc%9a%e9%80%9a%e8%bf%87%e6%b3%a8%e8%a7%a3%e9%85%8d%e7%bd%ae%e5%92%8c%e5%8c%85%e8%87%aa%e5%8a%a8%e6%89%ab%e6%8f%8f%e7%9a%84%e6%96%b9","status":"publish","type":"post","link":"http:\/\/www.cmd137blog.top\/?p=1294","title":{"rendered":"mini-Spring \u4ee3\u7406\u7bc7-AOP\uff1aStep 13\uff1a\u901a\u8fc7\u6ce8\u89e3\u914d\u7f6e\u548c\u5305\u81ea\u52a8\u626b\u63cf\u7684\u65b9\u5f0f\u5b8c\u6210Bean\u5bf9\u8c61\u7684\u6ce8\u518c"},"content":{"rendered":"\n<h1 class=\"wp-block-heading\">\u524d\u8a00\uff1a\u4e3a\u4f55\u5f15\u5165\u6ce8\u89e3 + \u626b\u63cf\u673a\u5236<\/h1>\n\n\n\n<p>\u5728\u4f20\u7edf\u7684 Spring \u5e94\u7528\u4e2d\uff0c\u5f00\u53d1\u8005\u9700\u8981\u5728 XML \u4e2d\u663e\u5f0f\u914d\u7f6e\u6bcf\u4e2a Bean\uff0c\u8fd9\u79cd\u65b9\u5f0f\u4e00\u65b9\u9762\u7e41\u7410\u3001\u96be\u4ee5\u7ef4\u62a4\uff1b\u53e6\u4e00\u65b9\u9762\u5982\u679c Bean \u6570\u91cf\u591a\u3001\u4f9d\u8d56\u590d\u6742\uff0c\u8fd8\u5bb9\u6613\u51fa\u9519\u3002\u73b0\u4ee3\u5e94\u7528\u66f4\u503e\u5411\u4e8e\u201c\u7ea6\u5b9a\u4f18\u4e8e\u914d\u7f6e\u201d\uff0c\u5b9e\u73b0\u81ea\u52a8\u5316\u6ce8\u518c\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u5f00\u53d1\u8005\u53ea\u9700\u5728\u7c7b\u4e0a\u589e\u52a0\u6ce8\u89e3\uff1b<\/li>\n\n\n\n<li>\u6846\u67b6\u901a\u8fc7\u626b\u63cf\u6307\u5b9a\u5305\u8def\u5f84\uff0c\u81ea\u52a8\u8bc6\u522b\u5e76\u6ce8\u518c\u6240\u6709\u76f8\u5173\u7ec4\u4ef6\uff1b<\/li>\n\n\n\n<li>\u914d\u7f6e\u5316\u5c5e\u6027\uff08\u5982 <code>${...}<\/code>\uff09\u5728 BeanDefinition \u52a0\u8f7d\u5b8c\u6210\u540e\u6ce8\u5165\uff0c\u652f\u6301\u5c5e\u6027\u5360\u4f4d\u7b26\u7075\u6d3b\u7ba1\u7406\u3002<\/li>\n<\/ul>\n\n\n\n<p>\u672c\u7ae0\u624b\u64b8 Spring\uff0c\u5c06\u91c7\u7528\u81ea\u5b9a\u4e49\u6ce8\u89e3\u4e0e\u5305\u626b\u63cf\u65b9\u5f0f\u66ff\u4ee3 XML \u7684\u663e\u5f0f\u6ce8\u518c\uff0c\u5e76\u7ed3\u5408 <code>BeanFactoryPostProcessor<\/code> \u5b9e\u73b0\u5360\u4f4d\u7b26\u914d\u7f6e\u6ce8\u5165\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u4e00\u3001\u529f\u80fd\u76ee\u6807<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u6ce8\u89e3\u6807\u8bb0 Bean<\/strong>\uff1a\u901a\u8fc7\u81ea\u5b9a\u4e49\u6ce8\u89e3\uff08\u5982 <code>@Component<\/code>\u3001<code>@Scope<\/code>\uff09\u6807\u8bc6\u5019\u9009 Bean\uff1b<\/li>\n\n\n\n<li><strong>\u5305\u8def\u5f84\u626b\u63cf<\/strong>\uff1a\u89e3\u6790 XML \u4e2d <code>&lt;context:component-scan&gt;<\/code> \u6307\u5b9a\u626b\u63cf\u8def\u5f84\uff1b<\/li>\n\n\n\n<li><strong>\u7c7b\u52a0\u8f7d\u4e0e\u6ce8\u89e3\u8bc6\u522b<\/strong>\uff1a\u626b\u63cf\u7c7b\u6587\u4ef6\uff0c\u8bc6\u522b\u6ce8\u89e3\uff0c\u8bfb\u53d6 bean \u540d\u79f0\u548c\u4f5c\u7528\u57df\uff1b<\/li>\n\n\n\n<li><strong>BeanDefinition \u6ce8\u518c<\/strong>\uff1a\u6839\u636e\u626b\u63cf\u7ed3\u679c\u7ec4\u88c5 <code>BeanDefinition<\/code> \u5e76\u6ce8\u518c\u5230\u5bb9\u5668\uff1b<\/li>\n\n\n\n<li><strong>\u5c5e\u6027\u5360\u4f4d\u7b26\u6ce8\u5165<\/strong>\uff1a\u5b9e\u73b0 <code>${\u2026}<\/code> \u5360\u4f4d\u7b26\u89e3\u6790\uff0c\u901a\u8fc7\u8bfb\u53d6\u914d\u7f6e\u6587\u4ef6\u586b\u5145\u5c5e\u6027\u3002<\/li>\n<\/ol>\n\n\n\n<p>\u901a\u8fc7\u4e0a\u8ff0\u529f\u80fd\uff0c\u5c06\u81ea\u52a8\u5b8c\u6210 Bean \u7684\u5b9a\u4e49\u3001\u6ce8\u518c\u4e0e\u5c5e\u6027\u6ce8\u5165\uff0c\u51cf\u5c11\u914d\u7f6e\u5197\u4f59\uff0c\u63d0\u5347\u5f00\u53d1\u6548\u7387\u548c\u7cfb\u7edf\u7075\u6d3b\u6027\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u4e8c\u3001\u8bbe\u8ba1\u65b9\u6848\u6982\u89c8<\/h2>\n\n\n\n<p>\u6838\u5fc3\u7ec4\u4ef6\u5982\u4e0b\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u5de5\u7a0b\u7ed3\u6784<\/strong>\uff1a\u589e\u52a0 <code>context.annotation<\/code> \u5305\u7528\u4e8e\u6ce8\u89e3\u4e0e\u626b\u63cf\u673a\u5236\uff1b<\/li>\n\n\n\n<li><strong>\u6ce8\u89e3\u5b9a\u4e49<\/strong>\uff1a<code>@Component<\/code> \u6807\u8bc6 Bean\uff0c<code>@Scope<\/code> \u5b9a\u4e49\u4f5c\u7528\u57df\uff1b<\/li>\n\n\n\n<li><strong>\u626b\u63cf\u5de5\u5177<\/strong>\uff1a\n<ul class=\"wp-block-list\">\n<li><code>ClassPathScanningCandidateComponentProvider<\/code> \u626b\u63cf\u5305\u4e2d\u7684\u6ce8\u89e3\u7c7b\uff1b<\/li>\n\n\n\n<li><code>ClassPathBeanDefinitionScanner<\/code> \u89e3\u6790\u6ce8\u89e3\u3001\u4f5c\u7528\u57df\u548c Bean \u540d\u79f0\uff1b<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>XML \u89e3\u6790\u589e\u5f3a<\/strong>\uff1a\u5728 <code>XmlBeanDefinitionReader#doLoadBeanDefinitions<\/code> \u4e2d\u52a0\u5165\u626b\u63cf\u89e3\u6790 <code>&lt;context:component-scan&gt;<\/code>\uff1b<\/li>\n\n\n\n<li><strong>\u5360\u4f4d\u7b26\u6ce8\u5165<\/strong>\uff1a\u901a\u8fc7\u5b9e\u73b0 <code>BeanFactoryPostProcessor<\/code>\uff0c\u5728 BeanDefinition \u52a0\u8f7d\u540e\u3001\u5b9e\u4f8b\u5316\u524d\u5904\u7406\u5360\u4f4d\u7b26\u3002<\/li>\n<\/ul>\n\n\n\n<p>\u6574\u4f53\u6d41\u7a0b\u5982\u4e0b\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u8bfb\u53d6 XML \u914d\u7f6e\uff1b<\/li>\n\n\n\n<li>\u5728XmlBeanDefinitionReader\u4e2d\u89e3\u6790\uff0c\u9047\u5230 <code>&lt;context:component-scan&gt;<\/code>\uff0c\u89e6\u53d1\u626b\u63cf\uff1b<\/li>\n\n\n\n<li>\u626b\u63cf\u6ce8\u89e3\u7c7b\u5e76\u751f\u6210 BeanDefinition\uff1b<\/li>\n\n\n\n<li>\u5c06 BeanDefinition \u6ce8\u5165 BeanFactory\uff1b<\/li>\n\n\n\n<li>\u5e94\u7528 <code>PropertyPlaceholderConfigurer<\/code> \u89e3\u6790 <code>${\u2026}<\/code> \u5e76\u66ff\u6362\u4e3a\u914d\u7f6e\u503c\uff1b<\/li>\n\n\n\n<li>\u6309\u5e38\u89c4\u6d41\u7a0b\u5b9e\u4f8b\u5316 Bean\u3002<\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-image\"><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/bugstack.cn\/assets\/images\/spring\/spring-14-01.png'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  decoding=\"async\" data-original=\"https:\/\/bugstack.cn\/assets\/images\/spring\/spring-14-01.png\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"\"\/><\/div><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">\u4e09\u3001\u67b6\u6784\uff1a<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"_1-\u5de5\u7a0b\u7ed3\u6784\">1. \u5de5\u7a0b\u7ed3\u6784<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>small-spring-step-13\n\u2514\u2500\u2500 src\n    \u251c\u2500\u2500 main\n    \u2502   \u2514\u2500\u2500 java\n    \u2502       \u2514\u2500\u2500 cn.bugstack.springframework\n    \u2502           \u251c\u2500\u2500 aop\n    \u2502           \u2502   \u251c\u2500\u2500 aspectj\n    \u2502           \u2502   \u2502   \u2514\u2500\u2500 AspectJExpressionPointcut.java\n    \u2502           \u2502   \u2502   \u2514\u2500\u2500 AspectJExpressionPointcutAdvisor.java\n    \u2502           \u2502   \u251c\u2500\u2500 framework \n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 adapter\n    \u2502           \u2502   \u2502   \u2502   \u2514\u2500\u2500 MethodBeforeAdviceInterceptor.java\n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 autoproxy\n    \u2502           \u2502   \u2502   \u2502   \u2514\u2500\u2500 MethodBeforeAdviceInterceptor.java\n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 AopProxy.java\n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 Cglib2AopProxy.java\n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 JdkDynamicAopProxy.java\n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 ProxyFactory.java\n    \u2502           \u2502   \u2502   \u2514\u2500\u2500 ReflectiveMethodInvocation.java\n    \u2502           \u2502   \u251c\u2500\u2500 AdvisedSupport.java\n    \u2502           \u2502   \u251c\u2500\u2500 Advisor.java\n    \u2502           \u2502   \u251c\u2500\u2500 BeforeAdvice.java\n    \u2502           \u2502   \u251c\u2500\u2500 ClassFilter.java\n    \u2502           \u2502   \u251c\u2500\u2500 MethodBeforeAdvice.java\n    \u2502           \u2502   \u251c\u2500\u2500 MethodMatcher.java\n    \u2502           \u2502   \u251c\u2500\u2500 Pointcut.java\n    \u2502           \u2502   \u251c\u2500\u2500 PointcutAdvisor.java\n    \u2502           \u2502   \u2514\u2500\u2500 TargetSource.java\n    \u2502           \u251c\u2500\u2500 beans\n    \u2502           \u2502   \u251c\u2500\u2500 factory\n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 config\n    \u2502           \u2502   \u2502   \u2502   \u251c\u2500\u2500 AutowireCapableBeanFactory.java\n    \u2502           \u2502   \u2502   \u2502   \u251c\u2500\u2500 BeanDefinition.java\n    \u2502           \u2502   \u2502   \u2502   \u251c\u2500\u2500 BeanFactoryPostProcessor.java\n    \u2502           \u2502   \u2502   \u2502   \u251c\u2500\u2500 BeanPostProcessor.java\n    \u2502           \u2502   \u2502   \u2502   \u251c\u2500\u2500 BeanReference.java\n    \u2502           \u2502   \u2502   \u2502   \u251c\u2500\u2500 ConfigurableBeanFactory.java\n    \u2502           \u2502   \u2502   \u2502   \u251c\u2500\u2500 InstantiationAwareBeanPostProcessor.java\n    \u2502           \u2502   \u2502   \u2502   \u2514\u2500\u2500 SingletonBeanRegistry.java\n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 support\n    \u2502           \u2502   \u2502   \u2502   \u251c\u2500\u2500 AbstractAutowireCapableBeanFactory.java\n    \u2502           \u2502   \u2502   \u2502   \u251c\u2500\u2500 AbstractBeanDefinitionReader.java\n    \u2502           \u2502   \u2502   \u2502   \u251c\u2500\u2500 AbstractBeanFactory.java\n    \u2502           \u2502   \u2502   \u2502   \u251c\u2500\u2500 BeanDefinitionReader.java\n    \u2502           \u2502   \u2502   \u2502   \u251c\u2500\u2500 BeanDefinitionRegistry.java\n    \u2502           \u2502   \u2502   \u2502   \u251c\u2500\u2500 CglibSubclassingInstantiationStrategy.java\n    \u2502           \u2502   \u2502   \u2502   \u251c\u2500\u2500 DefaultListableBeanFactory.java\n    \u2502           \u2502   \u2502   \u2502   \u251c\u2500\u2500 DefaultSingletonBeanRegistry.java\n    \u2502           \u2502   \u2502   \u2502   \u251c\u2500\u2500 DisposableBeanAdapter.java\n    \u2502           \u2502   \u2502   \u2502   \u251c\u2500\u2500 FactoryBeanRegistrySupport.java\n    \u2502           \u2502   \u2502   \u2502   \u251c\u2500\u2500 InstantiationStrategy.java\n    \u2502           \u2502   \u2502   \u2502   \u2514\u2500\u2500 SimpleInstantiationStrategy.java  \n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 support\n    \u2502           \u2502   \u2502   \u2502   \u2514\u2500\u2500 XmlBeanDefinitionReader.java\n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 Aware.java\n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 BeanClassLoaderAware.java\n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 BeanFactory.java\n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 BeanFactoryAware.java\n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 BeanNameAware.java\n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 ConfigurableListableBeanFactory.java\n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 DisposableBean.java\n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 FactoryBean.java\n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 HierarchicalBeanFactory.java\n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 InitializingBean.java\n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 ListableBeanFactory.java\n    \u2502           \u2502   \u2502   \u2514\u2500\u2500 PropertyPlaceholderConfigurer.java\n    \u2502           \u2502   \u251c\u2500\u2500 BeansException.java\n    \u2502           \u2502   \u251c\u2500\u2500 PropertyValue.java\n    \u2502           \u2502   \u2514\u2500\u2500 PropertyValues.java \n    \u2502           \u251c\u2500\u2500 context\n    \u2502           \u2502   \u251c\u2500\u2500 annotation\n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 ClassPathBeanDefinitionScanner.java \n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 ClassPathScanningCandidateComponentProvider.java \n    \u2502           \u2502   \u2502   \u2514\u2500\u2500 Scope.java \n    \u2502           \u2502   \u251c\u2500\u2500 event\n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 AbstractApplicationEventMulticaster.java \n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 ApplicationContextEvent.java \n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 ApplicationEventMulticaster.java \n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 ContextClosedEvent.java \n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 ContextRefreshedEvent.java \n    \u2502           \u2502   \u2502   \u2514\u2500\u2500 SimpleApplicationEventMulticaster.java \n    \u2502           \u2502   \u251c\u2500\u2500 support\n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 AbstractApplicationContext.java \n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 AbstractRefreshableApplicationContext.java \n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 AbstractXmlApplicationContext.java \n    \u2502           \u2502   \u2502   \u251c\u2500\u2500 ApplicationContextAwareProcessor.java \n    \u2502           \u2502   \u2502   \u2514\u2500\u2500 ClassPathXmlApplicationContext.java \n    \u2502           \u2502   \u251c\u2500\u2500 ApplicationContext.java \n    \u2502           \u2502   \u251c\u2500\u2500 ApplicationContextAware.java \n    \u2502           \u2502   \u251c\u2500\u2500 ApplicationEvent.java \n    \u2502           \u2502   \u251c\u2500\u2500 ApplicationEventPublisher.java \n    \u2502           \u2502   \u251c\u2500\u2500 ApplicationListener.java \n    \u2502           \u2502   \u2514\u2500\u2500 ConfigurableApplicationContext.java\n    \u2502           \u251c\u2500\u2500 core.io\n    \u2502           \u2502   \u251c\u2500\u2500 ClassPathResource.java \n    \u2502           \u2502   \u251c\u2500\u2500 DefaultResourceLoader.java \n    \u2502           \u2502   \u251c\u2500\u2500 FileSystemResource.java \n    \u2502           \u2502   \u251c\u2500\u2500 Resource.java \n    \u2502           \u2502   \u251c\u2500\u2500 ResourceLoader.java\n    \u2502           \u2502   \u2514\u2500\u2500 UrlResource.java\n    \u2502           \u251c\u2500\u2500 stereotype\n    \u2502           \u2502   \u2514\u2500\u2500 Component.java\n    \u2502           \u2514\u2500\u2500 utils\n    \u2502               \u2514\u2500\u2500 ClassUtils.java\n    \u2514\u2500\u2500 test\n        \u2514\u2500\u2500 java\n            \u2514\u2500\u2500 cn.bugstack.springframework.test\n                \u251c\u2500\u2500 bean\n                \u2502   \u251c\u2500\u2500 IUserService.java\n                \u2502   \u2514\u2500\u2500 UserService.java\n                \u2514\u2500\u2500 ApiTest.java\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">2.\u5728Bean\u7684\u751f\u547d\u5468\u671f\u4e2d\u81ea\u52a8\u52a0\u8f7d\u5305\u626b\u63cf\u6ce8\u518cBean\u5bf9\u8c61\u548c\u8bbe\u7f6e\u5360\u4f4d\u7b26\u5c5e\u6027\u7684\u7c7b\u5173\u7cfb<\/h2>\n\n\n\n<figure class=\"wp-block-image\"><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/bugstack.cn\/assets\/images\/spring\/spring-14-02.png'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  decoding=\"async\" data-original=\"https:\/\/bugstack.cn\/assets\/images\/spring\/spring-14-02.png\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"\u56fe 14-2\"\/><\/div><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">\u56db\u3001\u5b9e\u73b0\u8be6\u89e3\uff1a<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">1.\u6ce8\u89e3\u5b9a\u4e49<\/h2>\n\n\n\n<p>\u524d\u7f6e\u77e5\u8bc6\uff1a<a href=\"http:\/\/www.cmd137blog.top\/?p=671\">JAVA-\u6ce8\u89e3 Annotation \u2013 CMD137&#8217;s Blog<\/a><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/**\n * \u7528\u4e8e\u914d\u7f6e\u4f5c\u7528\u57df\u7684\u81ea\u5b9a\u4e49\u6ce8\u89e3\uff0c\u65b9\u4fbf\u901a\u8fc7\u914d\u7f6eBean\u5bf9\u8c61\u6ce8\u89e3\u7684\u65f6\u5019\uff0c\u62ff\u5230Bean\u5bf9\u8c61\u7684\u4f5c\u7528\u57df\u3002\u4e0d\u8fc7\u4e00\u822c\u90fd\u4f7f\u7528\u9ed8\u8ba4\u7684 singleton\n *\/\n@Target({ElementType.TYPE, ElementType.METHOD}) \/\/ \u53ef\u4f5c\u7528\u4e8e\u7c7b\u548c\u65b9\u6cd5\n@Retention(RetentionPolicy.RUNTIME)             \/\/ \u8fd0\u884c\u65f6\u53ef\u901a\u8fc7\u53cd\u5c04\u8bfb\u53d6\n@Documented                                     \/\/ \u751f\u6210 Javadoc \u65f6\u5305\u542b\u8be5\u6ce8\u89e3\u4fe1\u606f\npublic @interface Scope {\n    \/**\n     * \u4f5c\u7528\u57df\u503c\uff0c\u9ed8\u8ba4\u4e3a singleton\u3002\n     * @return \u4f5c\u7528\u57df\u540d\u79f0\n     *\/\n    String value() default \"singleton\";\n}\n<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>\n\/**\n * \u7ec4\u4ef6\u6ce8\u89e3\uff0c\u7528\u4e8e\u6807\u8bc6\u4e00\u4e2a\u7c7b\u4e3aSpring\u5bb9\u5668\u7ba1\u7406\u7684Bean\n * \u88ab\u6b64\u6ce8\u89e3\u6807\u8bb0\u7684\u7c7b\u4f1a\u88ab\u81ea\u52a8\u626b\u63cf\u5e76\u6ce8\u518c\u5230Spring\u5bb9\u5668\u4e2d\n *\/\n@Target(ElementType.TYPE)          \/\/ \u4ec5\u53ef\u4f5c\u7528\u4e8e\u7c7b\u3001\u63a5\u53e3\uff08\u5305\u62ec\u6ce8\u89e3\u7c7b\u578b\uff09\u3001\u679a\u4e3e\n@Retention(RetentionPolicy.RUNTIME) \/\/ \u8fd0\u884c\u65f6\u53ef\u901a\u8fc7\u53cd\u5c04\u8bfb\u53d6\n@Documented                         \/\/ \u751f\u6210 Javadoc \u65f6\u5305\u542b\u8be5\u6ce8\u89e3\u4fe1\u606f\npublic @interface Component {\n    \/**\n     * Bean \u540d\u79f0\uff0c\u53ef\u9009\u3002\n     * @return Bean \u540d\u79f0\n     *\/\n    String value() default \"\";\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">2.\u5904\u7406\u5bf9\u8c61\u626b\u63cf\u88c5\u914d\uff1a<\/h2>\n\n\n\n<p>\u8be5\u7c7b\u7684\u6838\u5fc3\u4f5c\u7528\u662f<strong>\u5728\u6307\u5b9a\u7684\u5305\u8def\u5f84\u4e0b\u626b\u63cf\u5e26\u6709\u7279\u5b9a\u6ce8\u89e3\u7684\u7c7b<\/strong>\uff0c\u5e76\u5c06\u8fd9\u4e9b\u7c7b\u8f6c\u6362\u4e3a\u7ec4\u4ef6\u5b9a\u4e49\uff08<code>BeanDefinition<\/code>\uff09\uff0c\u4e3a\u540e\u7eed\u7684\u5bf9\u8c61\u521b\u5efa\u548c\u7ba1\u7406\u63d0\u4f9b\u5143\u6570\u636e\u3002<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><em>\/**<br><\/em><em> * <\/em><em>\u5728\u57fa\u4e8e\u6ce8\u89e3\u7684 <\/em><em>Bean <\/em><em>\u6ce8\u518c\u673a\u5236\u4e2d\uff0c\u9700\u8981\u6709\u4e00\u4e2a\u6b65\u9aa4\u80fd\u4ece\u6307\u5b9a\u5305\u8def\u5f84\u4e2d\u53d1\u73b0\u7b26\u5408\u6761\u4ef6\u7684\u7c7b\uff0c<br><\/em><em> <\/em><em>* <\/em><em>\u5e76\u5c06\u5b83\u4eec\u4f5c\u4e3a\u5019\u9009\u7ec4\u4ef6\uff08<\/em><em>Candidate Component<\/em><em>\uff09\u4ea4\u7ed9 <\/em><em>BeanDefinition <\/em><em>\u6ce8\u518c\u6d41\u7a0b\u5904\u7406\u3002<br><\/em><em> <\/em><em>* <\/em><em>\u8be5\u7c7b\u5c31\u662f\u5b8c\u6210<\/em><em>\u201c<\/em><em>\u626b\u63cf <\/em><em>+ <\/em><em>\u8f6c\u6362<\/em><em>\u201d<\/em><em>\u8fd9\u4e00\u529f\u80fd\u7684\u6838\u5fc3\u5de5\u5177\u7c7b\u3002<br><\/em><em> <\/em><em>*\/<br><\/em><em><br><\/em>public class ClassPathScanningCandidateComponentProvider {<br><br>    <em>\/**<br><\/em><em>     * <\/em><em>\u626b\u63cf\u6307\u5b9a\u57fa\u7840\u5305\u8def\u5f84\uff0c\u67e5\u627e\u88ab <\/em><em>{<\/em><strong><em>@link <\/em><\/strong><em>Component<\/em><em>} <\/em><em>\u6ce8\u89e3\u6807\u8bb0\u7684\u7c7b\uff0c<br><\/em><em>     <\/em><em>* <\/em><em>\u5e76\u5c06\u5176\u5c01\u88c5\u4e3a <\/em><em>{<\/em><strong><em>@link <\/em><\/strong><em>BeanDefinition} <\/em><em>\u5bf9\u8c61\u96c6\u5408\u8fd4\u56de\u3002<br><\/em><em>     <\/em><em>*<br><\/em><em>     * <\/em><strong><em>@param <\/em><\/strong><em>basePackage <\/em><em>\u57fa\u7840\u5305\u8def\u5f84\uff08\u5982 <\/em><em>\"com.example.service\"<\/em><em>\uff09<br><\/em><em>     <\/em><em>* <\/em><strong><em>@return <\/em><\/strong><em>\u5019\u9009 <\/em><em>BeanDefinition <\/em><em>\u96c6\u5408<br><\/em><em>     <\/em><em>*\/<br><\/em><em>    <\/em>public Set&lt;BeanDefinition&gt; findCandidateComponents(String basePackage) {<br>        \/\/ \u7528 LinkedHashSet \u4fdd\u8bc1\u626b\u63cf\u7ed3\u679c\u6709\u5e8f\u4e14\u4e0d\u91cd\u590d<br>        Set&lt;BeanDefinition&gt; candidates = new LinkedHashSet&lt;&gt;();<br><br>        \/\/ \u8c03\u7528\u5de5\u5177\u65b9\u6cd5\u626b\u63cf\u51fa\u88ab @Component \u6807\u8bb0\u7684\u7c7b<br>        Set&lt;Class&lt;?&gt;&gt; classes = ClassUtil.<em>scanPackageByAnnotation<\/em>(basePackage, Component.class);<br><br>        \/\/ \u5c06\u626b\u63cf\u5230\u7684\u7c7b\u8f6c\u6362\u4e3a BeanDefinition \u5e76\u52a0\u5165\u96c6\u5408<br>        for (Class&lt;?&gt; clazz : classes) {<br>            candidates.add(new BeanDefinition(clazz));<br>        }<br><br>        return candidates;<br>    }<br>}<\/pre>\n\n\n\n<p>ClassPathBeanDefinitionScanner \u662f\u7ee7\u627f\u81ea ClassPathScanningCandidateComponentProvider \u7684\u5177\u4f53\u626b\u63cf\u5305\u5904\u7406\u7684\u7c7b\uff0c\u5728 doScan \u4e2d\u9664\u4e86\u83b7\u53d6\u5230\u626b\u63cf\u7684\u7c7b\u4fe1\u606f\u4ee5\u540e\uff0c\u8fd8\u9700\u8981\u83b7\u53d6 Bean \u7684\u4f5c\u7528\u57df\u548c\u7c7b\u540d\uff0c<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/**\n * \u8be5\u7c7b\u7684\u6838\u5fc3\u4f5c\u7528\u662f\u5728\u6307\u5b9a\u5305\u8def\u5f84\u4e0b\u626b\u63cf\u7b26\u5408\u6761\u4ef6\u7684\u7ec4\u4ef6\uff08\u7ee7\u627f\u7236\u7c7b\u7684\u626b\u63cf\u80fd\u529b\uff09\uff0c\n * \u5e76\u5c06\u8fd9\u4e9b\u7ec4\u4ef6\u7684\u5b9a\u4e49\uff08BeanDefinition\uff09\u6ce8\u518c\u5230 Bean \u5b9a\u4e49\u6ce8\u518c\u8868\uff08BeanDefinitionRegistry\uff09\u4e2d\uff0c\n * \u662f\u8fde\u63a5 \u201c\u7ec4\u4ef6\u626b\u63cf\u201d \u4e0e \u201c\u5bb9\u5668\u6ce8\u518c\u201d \u7684\u5173\u952e\u6865\u6881\u3002\n *\/\npublic class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {\n\n    \/\/ BeanDefinition \u6ce8\u518c\u5668\uff0c\u7528\u4e8e\u5c06\u626b\u63cf\u5230\u7684 BeanDefinition \u6ce8\u518c\u5230\u5bb9\u5668\n    private BeanDefinitionRegistry registry;\n\n    public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {\n        this.registry = registry;\n    }\n\n    \/**\n     * \u626b\u63cf\u6307\u5b9a\u7684\u57fa\u7840\u5305\u8def\u5f84\uff0c\u5e76\u6ce8\u518c\u7b26\u5408\u6761\u4ef6\u7684 BeanDefinition\n     *\/\n    public void doScan(String... basePackages) {\n        for (String basePackage : basePackages) {\n            \/\/ \u626b\u63cf\u8be5\u5305\u4e0b\u6240\u6709\u88ab @Component \u6807\u6ce8\u7684\u7c7b\uff0c\u8f6c\u6362\u6210 BeanDefinition \u96c6\u5408\n            Set&lt;BeanDefinition> candidates = findCandidateComponents(basePackage);\n\n            for (BeanDefinition beanDefinition : candidates) {\n                \/\/ \u89e3\u6790 Bean \u7684\u4f5c\u7528\u57df\uff08singleton\u3001prototype \u7b49\uff09\n                String beanScope = resolveBeanScope(beanDefinition);\n                if (StrUtil.isNotEmpty(beanScope)) {\n                    beanDefinition.setScope(beanScope);\n                }\n\n                \/\/ \u6ce8\u518c BeanDefinition \u5230\u5bb9\u5668\n                \/\/ determineBeanName() \u7528\u4e8e\u89e3\u6790 Bean \u540d\u79f0\uff08@Component value \u6216\u7c7b\u540d\u9996\u5b57\u6bcd\u5c0f\u5199\uff09\n                registry.registerBeanDefinition(determineBeanName(beanDefinition), beanDefinition);\n            }\n        }\n    }\n\n    \/**\n     * \u6839\u636e @Scope \u6ce8\u89e3\u89e3\u6790 Bean \u7684\u4f5c\u7528\u57df\n     *\/\n    private String resolveBeanScope(BeanDefinition beanDefinition) {\n        Class&lt;?> beanClass = beanDefinition.getBeanClass();\n        Scope scope = beanClass.getAnnotation(Scope.class);\n        if (null != scope) return scope.value(); \/\/ \u5982\u679c\u6709 @Scope \u6ce8\u89e3\uff0c\u8fd4\u56de\u5176\u503c\n        return StrUtil.EMPTY; \/\/ \u9ed8\u8ba4\u8fd4\u56de\u7a7a\u5b57\u7b26\u4e32\uff0c\u8868\u793a\u4f7f\u7528\u9ed8\u8ba4\u4f5c\u7528\u57df\uff08singleton\uff09\n    }\n\n    \/**\n     * \u6839\u636e @Component \u6ce8\u89e3\u89e3\u6790 Bean \u7684\u540d\u79f0\n     * \u5982\u679c @Component value \u4e3a\u7a7a\uff0c\u5219\u4f7f\u7528\u7c7b\u540d\u9996\u5b57\u6bcd\u5c0f\u5199\n     *\/\n    private String determineBeanName(BeanDefinition beanDefinition) {\n        Class&lt;?> beanClass = beanDefinition.getBeanClass();\n        Component component = beanClass.getAnnotation(Component.class);\n        String value = component.value();\n        if (StrUtil.isEmpty(value)) {\n            \/\/ \u4f8b\u5982 UserService -> userService\n            value = StrUtil.lowerFirst(beanClass.getSimpleName());\n        }\n        return value;\n    }\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>\u6b64\u5904\u7b80\u5355\u63d0\u4e00\u5634\u540c\u540dBean\u7684\u95ee\u9898\uff1a<\/strong><\/h3>\n\n\n\n<p><strong>\u771f\u5b9e Spring \u7684\u5904\u7406\u903b\u8f91<\/strong>\uff1a<br>\u5728 Spring \u6846\u67b6\u4e2d\uff0c<code>DefaultListableBeanFactory.registerBeanDefinition<\/code> \u4f1a\u5148\u68c0\u67e5\u5bb9\u5668\u4e2d\u662f\u5426\u5df2\u5b58\u5728\u540c\u540d BeanDefinition\u3002\u5982\u679c\u5b58\u5728\uff0c\u9ed8\u8ba4\u5141\u8bb8\u8986\u76d6\uff0c\u5e76\u4f1a\u5728\u65e5\u5fd7\u4e2d\u8f93\u51fa\u8986\u76d6\u4fe1\u606f\uff0c\u63d0\u793a\u5f00\u53d1\u8005\u54ea\u4e2a BeanDefinition \u88ab\u66ff\u6362\u3002\u5982\u679c\u5f00\u53d1\u8005\u5c06 <code>allowBeanDefinitionOverriding<\/code> \u8bbe\u7f6e\u4e3a <code>false<\/code>\uff0c\u5219\u9047\u5230\u540c\u540d Bean \u4f1a\u629b\u51fa <code>BeanDefinitionOverrideException<\/code>\uff0c\u4ece\u800c\u7981\u6b62\u91cd\u590d\u6ce8\u518c\u3002\u8fd9\u79cd\u673a\u5236\u65e2\u4fdd\u8bc1\u4e86\u542f\u52a8\u7075\u6d3b\u6027\uff0c\u53c8\u63d0\u4f9b\u4e86\u5b89\u5168\u68c0\u67e5\u4e0e\u8c03\u8bd5\u63d0\u793a\u3002<\/p>\n\n\n\n<p><strong>mini-spring \u7684\u5904\u7406\u903b\u8f91<\/strong>\uff1a<br>\u5728 mini-spring \u4e2d\uff0c<code>ClassPathBeanDefinitionScanner<\/code> \u626b\u63cf\u5230\u7684\u540c\u540d Bean \u5728\u6ce8\u518c\u65f6\u76f4\u63a5\u8c03\u7528 <code>BeanDefinitionRegistry.registerBeanDefinition<\/code> \u5b58\u5165 Map\u3002\u7531\u4e8e\u9ed8\u8ba4\u6ca1\u6709\u505a\u91cd\u590d\u68c0\u6d4b\uff0c\u540e\u6ce8\u518c\u7684 BeanDefinition \u4f1a\u76f4\u63a5\u8986\u76d6\u4e4b\u524d\u6ce8\u518c\u7684\u540c\u540d Bean\uff0c\u5bb9\u5668\u4e2d\u53ea\u4fdd\u7559\u6700\u540e\u4e00\u4e2a\u6ce8\u518c\u7684 Bean\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3.\u5904\u7406\u5360\u4f4d\u7b26\u914d\u7f6e PropertyPlaceholderConfigurer\uff1a<\/h2>\n\n\n\n<p><strong>\u529f\u80fd<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u7528\u4e8e\u89e3\u6790 Bean \u5b9a\u4e49\u4e2d\u5c5e\u6027\u7684\u5360\u4f4d\u7b26\uff08placeholder\uff09\uff0c\u4f8b\u5982 <code>${property.name}<\/code>\u3002<\/li>\n\n\n\n<li>\u5c06\u5360\u4f4d\u7b26\u66ff\u6362\u4e3a\u771f\u5b9e\u7684\u503c\uff0c\u901a\u5e38\u6765\u81ea\u5916\u90e8\u914d\u7f6e\u6587\u4ef6\uff08<code>.properties<\/code>\uff09\u6216\u8005\u73af\u5883\u53d8\u91cf\u3002<\/li>\n<\/ul>\n\n\n\n<p><strong>\u4f5c\u7528<\/strong><\/p>\n\n\n\n<p>\u907f\u514d\u786c\u7f16\u7801\uff1a\u4f8b\u5982\u6570\u636e\u5e93 URL\u3001\u7528\u6237\u540d\u3001\u5bc6\u7801\u3001API Key \u7b49\u53ef\u4ee5\u7edf\u4e00\u5728\u914d\u7f6e\u6587\u4ef6\u7ba1\u7406\u3002<br>\u5b9e\u73b0<strong>\u5c5e\u6027\u5916\u90e8\u5316<\/strong>\uff1a\u914d\u7f6e\u4e0e\u4ee3\u7801\u5206\u79bb\uff0c\u63d0\u9ad8\u7075\u6d3b\u6027\u3002<br>\u652f\u6301<strong>\u7edf\u4e00\u7ba1\u7406<\/strong>\uff1a\u591a\u4e2a Bean \u53ef\u4ee5\u5171\u4eab\u540c\u4e00\u4e2a\u914d\u7f6e\u5c5e\u6027\u3002<\/p>\n\n\n\n<p><code>PropertyPlaceholderConfigurer<\/code> \u672c\u8d28\u4e0a\u662f\u4e00\u4e2a <strong>BeanFactoryPostProcessor<\/strong>\uff0c\u5b83\u5728 <strong>Bean \u5b9e\u4f8b\u5316\u4e4b\u524d<\/strong>\u5de5\u4f5c\u3002\u6d41\u7a0b\u5982\u4e0b\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u52a0\u8f7d\u914d\u7f6e\u6587\u4ef6<\/strong>\n<ul class=\"wp-block-list\">\n<li>\u901a\u8fc7 <code>location<\/code> \u5c5e\u6027\u8bfb\u53d6 <code>.properties<\/code> \u6587\u4ef6\uff0c\u52a0\u8f7d\u5230 <code>Properties<\/code> \u5bf9\u8c61\u4e2d\u3002<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>\u904d\u5386 BeanDefinition<\/strong>\n<ul class=\"wp-block-list\">\n<li>\u904d\u5386\u5bb9\u5668\u4e2d\u6240\u6709\u5df2\u6ce8\u518c\u7684 BeanDefinition\uff08\u6b64\u65f6 Bean \u8fd8\u672a\u5b9e\u4f8b\u5316\uff09\u3002<\/li>\n\n\n\n<li>\u67e5\u627e\u5c5e\u6027\u503c\u4e2d\u662f\u5426\u5305\u542b\u5360\u4f4d\u7b26 <code>${...}<\/code>\u3002<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>\u5360\u4f4d\u7b26\u66ff\u6362<\/strong>\n<ul class=\"wp-block-list\">\n<li>\u6839\u636e key \u4ece Properties \u4e2d\u83b7\u53d6\u5bf9\u5e94\u7684\u503c\u3002<\/li>\n\n\n\n<li>\u5c06 BeanDefinition \u7684\u5c5e\u6027\u503c\u66ff\u6362\u6210\u771f\u5b9e\u503c\u3002<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Bean \u5b9e\u4f8b\u5316\u65f6\u4f7f\u7528<\/strong>\n<ul class=\"wp-block-list\">\n<li>\u5f53\u5bb9\u5668\u771f\u6b63\u5b9e\u4f8b\u5316 Bean \u65f6\uff0c\u5c5e\u6027\u5df2\u7ecf\u662f\u6700\u7ec8\u66ff\u6362\u540e\u7684\u503c\uff0c\u4e0d\u9700\u8981\u518d\u6b21\u89e3\u6790\u3002<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>\/**\n * \u8be5\u7c7b\u5b9e\u73b0\u4e86Spring\u7684BeanFactoryPostProcessor\u63a5\u53e3\uff0c\n * \u7528\u4e8e\u5904\u7406Bean\u5b9a\u4e49\u4e2d\u7684\u5c5e\u6027\u5360\u4f4d\u7b26\uff0c\u5c06${...}\u5f62\u5f0f\u7684\u5360\u4f4d\u7b26\u66ff\u6362\u4e3a\u5c5e\u6027\u6587\u4ef6\u4e2d\u7684\u5b9e\u9645\u503c\n *\/\npublic class PropertyPlaceholderConfigurer implements BeanFactoryPostProcessor {\n\n    \/**\n     * \u9ed8\u8ba4\u7684\u5360\u4f4d\u7b26\u524d\u7f00: {@value}\n     *\/\n    public static final String DEFAULT_PLACEHOLDER_PREFIX = \"${\";\n\n    \/**\n     * \u9ed8\u8ba4\u7684\u5360\u4f4d\u7b26\u540e\u7f00: {@value}\n     *\/\n    public static final String DEFAULT_PLACEHOLDER_SUFFIX = \"}\";\n\n    \/\/ \u5c5e\u6027\u6587\u4ef6\u7684\u4f4d\u7f6e\n    private String location;\n\n    \/**\n     * \u5b9e\u73b0BeanFactoryPostProcessor\u63a5\u53e3\u7684\u65b9\u6cd5\uff0c\u5728BeanFactory\u52a0\u8f7d\u5b8c\u6240\u6709Bean\u5b9a\u4e49\u540e\u6267\u884c\n     * \u7528\u4e8e\u66ff\u6362Bean\u5b9a\u4e49\u4e2d\u7684\u5c5e\u6027\u5360\u4f4d\u7b26\n     * @param beanFactory \u53ef\u914d\u7f6e\u7684Bean\u5de5\u5382\uff0c\u7528\u4e8e\u83b7\u53d6\u548c\u4fee\u6539Bean\u5b9a\u4e49\n     * @throws BeansException \u5982\u679c\u5904\u7406\u8fc7\u7a0b\u4e2d\u53d1\u751f\u9519\u8bef\n     *\/\n    @Override\n    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {\n        \/\/ \u52a0\u8f7d\u5c5e\u6027\u6587\u4ef6\u5e76\u66ff\u6362\u5360\u4f4d\u7b26\n        try {\n            \/\/ \u521b\u5efa\u9ed8\u8ba4\u7684\u8d44\u6e90\u52a0\u8f7d\u5668\uff0c\u7528\u4e8e\u52a0\u8f7d\u5c5e\u6027\u6587\u4ef6\n            DefaultResourceLoader resourceLoader = new DefaultResourceLoader();\n            \/\/ \u6839\u636e\u914d\u7f6e\u7684\u4f4d\u7f6e\u52a0\u8f7d\u8d44\u6e90\n            Resource resource = resourceLoader.getResource(location);\n            \/\/ \u521b\u5efaProperties\u5bf9\u8c61\u5e76\u52a0\u8f7d\u8d44\u6e90\u4e2d\u7684\u5c5e\u6027\n            Properties properties = new Properties();\n            properties.load(resource.getInputStream());\n\n            \/\/ \u83b7\u53d6\u6240\u6709Bean\u5b9a\u4e49\u7684\u540d\u79f0\n            String&#91;] beanDefinitionNames = beanFactory.getBeanDefinitionNames();\n            \/\/ \u904d\u5386\u6bcf\u4e2aBean\u5b9a\u4e49\n            for (String beanName : beanDefinitionNames) {\n                \/\/ \u83b7\u53d6\u5f53\u524dBean\u7684\u5b9a\u4e49\u4fe1\u606f\n                BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);\n\n                \/\/ \u83b7\u53d6Bean\u5b9a\u4e49\u4e2d\u7684\u6240\u6709\u5c5e\u6027\u503c\n                PropertyValues propertyValues = beanDefinition.getPropertyValues();\n                \/\/ \u904d\u5386\u6bcf\u4e2a\u5c5e\u6027\u503c\n                for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {\n                    \/\/ \u83b7\u53d6\u5c5e\u6027\u503c\u5bf9\u8c61\n                    Object value = propertyValue.getValue();\n                    \/\/ \u5982\u679c\u5c5e\u6027\u503c\u4e0d\u662f\u5b57\u7b26\u4e32\u7c7b\u578b\uff0c\u5219\u8df3\u8fc7\n                    if (!(value instanceof String)) continue;\n                    String strVal = (String) value;\n\n                    \/\/ \u67e5\u627e\u5360\u4f4d\u7b26\u524d\u7f00\u7684\u4f4d\u7f6e\n                    int startIdx = strVal.indexOf(DEFAULT_PLACEHOLDER_PREFIX);\n                    \/\/ \u67e5\u627e\u5360\u4f4d\u7b26\u540e\u7f00\u7684\u4f4d\u7f6e\n                    int stopIdx = strVal.indexOf(DEFAULT_PLACEHOLDER_SUFFIX);\n\n                    \/\/ \u5982\u679c\u627e\u5230\u4e86\u6709\u6548\u7684\u5360\u4f4d\u7b26\uff08\u524d\u7f00\u5728\u540e\u7f00\u4e4b\u524d\uff09\n                    if (startIdx != -1 &amp;&amp; stopIdx != -1 &amp;&amp; startIdx &lt; stopIdx) {\n                        \/\/ \u63d0\u53d6\u5360\u4f4d\u7b26\u4e2d\u7684\u5c5e\u6027\u952e\uff08\u53bb\u6389\u524d\u7f00\u548c\u540e\u7f00\uff09\n                        String propKey = strVal.substring(startIdx + 2, stopIdx);\n                        \/\/ \u4ece\u5c5e\u6027\u6587\u4ef6\u4e2d\u83b7\u53d6\u5bf9\u5e94\u7684\u5c5e\u6027\u503c\n                        String propVal = properties.getProperty(propKey);\n                        \/\/ \u66ff\u6362\u5360\u4f4d\u7b26\u4e3a\u5b9e\u9645\u5c5e\u6027\u503c\n                        String newValue = strVal.replace(DEFAULT_PLACEHOLDER_PREFIX + propKey + DEFAULT_PLACEHOLDER_SUFFIX, propVal);\n                        \/\/ \u66f4\u65b0Bean\u5b9a\u4e49\u4e2d\u7684\u5c5e\u6027\u503c\n                        propertyValues.addPropertyValue(new PropertyValue(propertyValue.getName(), newValue));\n                    }\n                }\n            }\n        } catch (IOException e) {\n            \/\/ \u5982\u679c\u52a0\u8f7d\u5c5e\u6027\u6587\u4ef6\u5931\u8d25\uff0c\u629b\u51fa\u5f02\u5e38\n            throw new BeansException(\"Could not load properties\", e);\n        }\n    }\n\n    \/**\n     * \u8bbe\u7f6e\u5c5e\u6027\u6587\u4ef6\u7684\u4f4d\u7f6e\n     * @param location \u5c5e\u6027\u6587\u4ef6\u7684\u8def\u5f84\n     *\/\n    public void setLocation(String location) {\n        this.location = location;\n    }\n\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">4.\u89e3\u6790xml\uff08<strong>XmlBeanDefinitionReader<\/strong>\uff09\u4e2d\u8c03\u7528\u626b\u63cf\uff1a<\/h2>\n\n\n\n<p>\u6b64\u5904\u4e3b\u8981\u4fee\u6539\u4e86doLoadBeanDefinitions\uff0c\u6362\u4e86\u53e6\u4e00\u4e2a\u5305\uff08dom4j\uff09\u6765\u89e3\u6790xml\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>protected void doLoadBeanDefinitions(InputStream inputStream) throws ClassNotFoundException, DocumentException {\n    \/\/ 1. \u521b\u5efa SAXReader \u5bf9\u8c61\uff0c\u4f7f\u7528 dom4j \u89e3\u6790 XML\n    SAXReader reader = new SAXReader();\n    \/\/ 2. \u8bfb\u53d6\u8f93\u5165\u6d41\uff0c\u751f\u6210 Document \u5bf9\u8c61\uff08DOM \u6811\uff09\n    Document document = reader.read(inputStream);\n    \/\/ 3. \u83b7\u53d6\u6839\u5143\u7d20 &lt;beans>\n    Element root = document.getRootElement();\n\n    \/\/ ---------------------------\n    \/\/ 4. \u89e3\u6790 &lt;context:component-scan> \u6807\u7b7e\n    \/\/    \u76ee\u7684\u662f\u626b\u63cf\u6307\u5b9a\u5305\u4e0b\u7684\u7c7b\u5e76\u751f\u6210 BeanDefinition\n    \/\/ ---------------------------\n    Element componentScan = root.element(\"component-scan\");\n    if (componentScan != null) {\n        \/\/ 5. \u83b7\u53d6 base-package \u5c5e\u6027\u503c\uff0c\u652f\u6301\u9017\u53f7\u5206\u9694\u591a\u4e2a\u5305\n        String scanPath = componentScan.attributeValue(\"base-package\");\n        \/\/ 6. \u5982\u679c base-package \u4e3a\u7a7a\uff0c\u629b\u51fa\u5f02\u5e38\n        if (StrUtil.isEmpty(scanPath)) {\n            throw new BeansException(\"The value of base-package attribute can not be empty or null\");\n        }\n        \/\/ 7. \u8c03\u7528 scanPackage \u65b9\u6cd5\u626b\u63cf\u5305\n        scanPackage(scanPath);\n    }\n\n    \/\/ ---------------------------\n    \/\/ 8. \u89e3\u6790 &lt;bean> \u6807\u7b7e\n    \/\/ ---------------------------\n    List&lt;Element> beanList = root.elements(\"bean\");\n    for (Element bean : beanList) {\n        \/\/ 9. \u83b7\u53d6 bean \u6807\u7b7e\u7684\u57fa\u672c\u5c5e\u6027\uff1aid\u3001name\u3001class\u3001init-method\u3001destroy-method\u3001scope\n        String id = bean.attributeValue(\"id\");\n        String name = bean.attributeValue(\"name\");\n        String className = bean.attributeValue(\"class\");\n        String initMethod = bean.attributeValue(\"init-method\");\n        String destroyMethodName = bean.attributeValue(\"destroy-method\");\n        String beanScope = bean.attributeValue(\"scope\");\n\n        \/\/ 10. \u6839\u636e class \u5c5e\u6027\u83b7\u53d6 Class \u5bf9\u8c61\n        Class&lt;?> clazz = Class.forName(className);\n        \/\/ 11. \u786e\u5b9a Bean \u540d\u79f0\uff0c\u4f18\u5148\u4f7f\u7528 id\uff0c\u5176\u6b21 name\uff0c\u6700\u540e\u7c7b\u540d\u9996\u5b57\u6bcd\u5c0f\u5199\n        String beanName = StrUtil.isNotEmpty(id) ? id : name;\n        if (StrUtil.isEmpty(beanName)) {\n            beanName = StrUtil.lowerFirst(clazz.getSimpleName());\n        }\n\n        \/\/ 12. \u521b\u5efa BeanDefinition \u5bf9\u8c61\uff0c\u7528\u4e8e\u5c01\u88c5 bean \u4fe1\u606f\n        BeanDefinition beanDefinition = new BeanDefinition(clazz);\n        beanDefinition.setInitMethodName(initMethod);\n        beanDefinition.setDestroyMethodName(destroyMethodName);\n        \/\/ 13. \u5982\u679c scope \u4e0d\u4e3a\u7a7a\uff0c\u8bbe\u7f6e\u5230 BeanDefinition\n        if (StrUtil.isNotEmpty(beanScope)) {\n            beanDefinition.setScope(beanScope);\n        }\n\n        \/\/ ---------------------------\n        \/\/ 14. \u89e3\u6790 &lt;property> \u5b50\u6807\u7b7e\n        \/\/    \u7528\u4e8e\u8bfb\u53d6 Bean \u5c5e\u6027\u5e76\u5c01\u88c5\u6210 PropertyValue \u5bf9\u8c61\n        \/\/ ---------------------------\n        List&lt;Element> propertyList = bean.elements(\"property\");\n        for (Element property : propertyList) {\n            \/\/ 15. \u83b7\u53d6\u5c5e\u6027\u540d\u3001\u5c5e\u6027\u503c\u3001\u5f15\u7528\n            String attrName = property.attributeValue(\"name\");\n            String attrValue = property.attributeValue(\"value\");\n            String attrRef = property.attributeValue(\"ref\");\n            \/\/ 16. \u5224\u65ad\u662f\u5f15\u7528\u5176\u4ed6 Bean \u8fd8\u662f\u666e\u901a\u503c\n            Object value = StrUtil.isNotEmpty(attrRef) ? new BeanReference(attrRef) : attrValue;\n            \/\/ 17. \u5c01\u88c5\u5c5e\u6027\u540d\u548c\u503c\u5230 PropertyValue\n            PropertyValue propertyValue = new PropertyValue(attrName, value);\n            \/\/ 18. \u6dfb\u52a0\u5230 BeanDefinition \u7684\u5c5e\u6027\u96c6\u5408\u4e2d\n            beanDefinition.getPropertyValues().addPropertyValue(propertyValue);\n        }\n\n        \/\/ 19. \u68c0\u67e5\u5bb9\u5668\u4e2d\u662f\u5426\u5df2\u6709\u540c\u540d Bean\uff0c\u9632\u6b62\u91cd\u590d\u6ce8\u518c\n        if (getRegistry().containsBeanDefinition(beanName)) {\n            throw new BeansException(\"Duplicate beanName&#91;\" + beanName + \"] is not allowed\");\n        }\n\n        \/\/ 20. \u6ce8\u518c BeanDefinition \u5230\u6ce8\u518c\u8868\u4e2d\n        getRegistry().registerBeanDefinition(beanName, beanDefinition);\n    }\n}\n\n\/**\n * \u626b\u63cf\u6307\u5b9a\u7684\u5305\u8def\u5f84\uff0c\u751f\u6210 BeanDefinition \u5e76\u6ce8\u518c\u5230\u5bb9\u5668\n * @param scanPath \u9017\u53f7\u5206\u9694\u7684\u57fa\u7840\u5305\u8def\u5f84\n *\/\nprivate void scanPackage(String scanPath) {\n    \/\/ 1. \u5206\u5272\u591a\u4e2a\u5305\u540d\n    String&#91;] basePackages = StrUtil.splitToArray(scanPath, ',');\n    \/\/ 2. \u521b\u5efa\u626b\u63cf\u5668\uff0c\u4f20\u5165 BeanDefinition \u6ce8\u518c\u5668\n    ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(getRegistry());\n    \/\/ 3. \u6267\u884c\u626b\u63cf\u5e76\u6ce8\u518c BeanDefinition\n    scanner.doScan(basePackages);\n}\n<\/code><\/pre>\n\n\n\n<h1 class=\"wp-block-heading\">\u6d4b\u8bd5\uff1a<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">1.\u6d4b\u8bd5\u7c7b\uff1a<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>@Component(\"userService\")\npublic class UserService implements IUserService {\n\n    private String token;\n\n    public String queryUserInfo() {\n        try {\n            Thread.sleep(new Random(1).nextInt(100));\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        }\n        return \"CMD137\uff0c100001\uff0c\u6df1\u5733\";\n    }\n\n    public String register(String userName) {\n        try {\n            Thread.sleep(new Random(1).nextInt(100));\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        }\n        return \"\u6ce8\u518c\u7528\u6237\uff1a\" + userName + \" success\uff01\";\n    }\n\n    @Override\n    public String toString() {\n        return \"UserService#token = { \" + token + \" }\";\n    }\n\n    public String getToken() {\n        return token;\n    }\n\n    public void setToken(String token) {\n        this.token = token;\n    }\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">2.\u5c5e\u6027\u914d\u7f6e\u6587\u4ef6 classpath:token.properties\uff1a<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>token=123_TEST_TOKEN_321<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">3.xml \u914d\u7f6e\u6587\u4ef6\uff1a<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">3.1 <strong>spring-property.xml<\/strong>\uff1a<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?>\n&lt;beans>\n\n    &lt;bean class=\"com.miniSpring.beans.factory.PropertyPlaceholderConfigurer\">\n        &lt;property name=\"location\" value=\"classpath:token.properties\"\/>\n    &lt;\/bean>\n\n    &lt;bean id=\"userService\" class=\"com.miniSpring.test.bean.UserService\">\n        &lt;property name=\"token\" value=\"${token}\"\/>\n    &lt;\/bean>\n\n&lt;\/beans>\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>3.2 <strong>spring-scan.xml<\/strong><\/strong>\uff1a<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?>\n&lt;beans>\n    &lt;component-scan base-package=\"com.miniSpring.test.bean\"\/>\n&lt;\/beans><\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">4.\u5355\u5143\u6d4b\u8bd5\uff1a<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">4.1 \u6d4b\u8bd5\u5305\u626b\u63cf\uff1a<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>@Test\npublic void test_scan() {\n    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(\"classpath:spring-scan.xml\");\n    IUserService userService = applicationContext.getBean(\"userService\", IUserService.class);\n    System.out.println(\"\u6d4b\u8bd5\u7ed3\u679c\uff1a\" + userService.queryUserInfo());\n}\n<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>\u6d4b\u8bd5\u7ed3\u679c\uff1aCMD137\uff0c100001\uff0c\u6df1\u5733\n\nProcess finished with exit code 0<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">4.2 \u6d4b\u8bd5\u5360\u4f4d\u7b26\u914d\u7f6e\uff1a<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>@Test\npublic void test_property() {\n    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(\"classpath:spring-property.xml\");\n    IUserService userService = applicationContext.getBean(\"userService\", IUserService.class);\n    System.out.println(\"\u6d4b\u8bd5\u7ed3\u679c\uff1a\" + userService);\n}\n<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>\u6d4b\u8bd5\u7ed3\u679c\uff1aUserService#token = { 123_TEST_TOKEN_321 }\n\nProcess finished with exit code 0<\/code><\/pre>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u524d\u8a00\uff1a\u4e3a\u4f55\u5f15\u5165\u6ce8\u89e3 + \u626b\u63cf\u673a\u5236 \u5728\u4f20\u7edf\u7684 Spring \u5e94\u7528\u4e2d\uff0c\u5f00\u53d1\u8005\u9700\u8981\u5728 XML \u4e2d\u663e\u5f0f\u914d\u7f6e\u6bcf\u4e2a Bea [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[66],"tags":[],"class_list":["post-1294","post","type-post","status-publish","format-standard","hentry","category-66"],"_links":{"self":[{"href":"http:\/\/www.cmd137blog.top\/index.php?rest_route=\/wp\/v2\/posts\/1294","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.cmd137blog.top\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.cmd137blog.top\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.cmd137blog.top\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.cmd137blog.top\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1294"}],"version-history":[{"count":3,"href":"http:\/\/www.cmd137blog.top\/index.php?rest_route=\/wp\/v2\/posts\/1294\/revisions"}],"predecessor-version":[{"id":1297,"href":"http:\/\/www.cmd137blog.top\/index.php?rest_route=\/wp\/v2\/posts\/1294\/revisions\/1297"}],"wp:attachment":[{"href":"http:\/\/www.cmd137blog.top\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1294"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.cmd137blog.top\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1294"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.cmd137blog.top\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1294"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}