1.【Spring注解驱动开发】二狗子让我给他讲讲@EnableAspectJAutoProxy注解
2.Spring源码系列-BeanPostProcessor与BeanFactoryPostProcessor
3.@Import({ AutoConfigurationImportSelector.class})
4.Spring源码- 02 Spring IoC容器启动之refresh方法
5.springçç»ä»¶åä½ç¨(springclouç»ä»¶)
6.什么是容容器AOP、IOC他们的器源作用是什么?
【Spring注解驱动开发】二狗子让我给他讲讲@EnableAspectJAutoProxy注解
在配置类上添加@EnableAspectJAutoProxy注解,能够开启注解版的实现AOP功能。这意味着,原理如果在AOP中要启用注解版的容容器AOP功能,就需要在配置类上添加@EnableAspectJAutoProxy注解。器源x播源码让我们来看看@EnableAspectJAutoProxy注解的实现源码,如下所示。原理
从源码可以看出,容容器@EnableAspectJAutoProxy注解使用@Import注解引入了AspectJAutoProxyRegister.class对象。器源那么,实现AspectJAutoProxyRegistrar是原理做什么的呢?我们点击到AspectJAutoProxyRegistrar类的源码中,如下所示。容容器
可以看到AspectJAutoProxyRegistrar类实现了ImportBeanDefinitionRegistrar接口。器源我们回顾ImportBeanDefinitionRegistrar接口的实现定义,如下所示。
通过ImportBeanDefinitionRegistrar接口,我们可以实现将自定义的组件添加到IOC容器中。也就是说,@EnableAspectJAutoProxy注解使用AspectJAutoProxyRegistrar对象自定义组件,并将相应的组件添加到IOC容器中。
在AspectJAutoProxyRegistrar类的registerBeanDefinitions()方法中设置断点,我们以debug的方法来运行AopTest类的testAop()方法。当程序运行到断点位置时,我们可以看到程序已经暂停,IDEA的左下角显示了方法的调用栈。
在registerBeanDefinitions()方法中,首先调用AopConfigUtils类的registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法来注册registry。在registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法中,直接调用了重载的registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法。在重载的registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法中,传入了AnnotationAwareAspectJAutoProxyCreator.class对象。
在registerOrEscalateApcAsRequired()方法中,接收到的Class对象的类型为:org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator。然后,盗q钓鱼源码我们继续跟进代码。
在registerOrEscalateApcAsRequired()方法中,首先判断registry是否包含org.springframework.aop.config.internalAutoProxyCreator类型的bean。接下来,我们继续看代码。
最终,AopConfigUtils类的registerOrEscalateApcAsRequired()方法中,会通过registry调用registerBeanDefinition()方法注册组件,并注册的bean的名称为org.springframework.aop.config.internalAutoProxyCreator。
接下来,我们继续看AspectJAutoProxyRegistrar类的registerBeanDefinitions()源码。我们通过AnnotationConfigUtils类的attributesFor方法来获取@EnableAspectJAutoProxy注解的信息。接下来,我们继续判断proxyTargetClass属性的值是否为true,如果为true则调用AopConfigUtils类的forceAutoProxyCreatorToUseClassProxying()方法;继续判断exposeProxy属性的值是否为true,如果为true则调用AopConfigUtils类的forceAutoProxyCreatorToExposeProxy()方法。
综上所述,向Spring的配置类上添加@EnableAspectJAutoProxy注解后,会向IOC容器中注册AnnotationAwareAspectJAutoProxyCreator。
了解了这些之后,我们就可以关注「冰河技术」微信公众号,后台回复不同的关键字获取相应的PDF文档。这些文档都是由冰河原创并整理的超硬核教程,包括《深入浅出Java 种设计模式》、《Java8新特性教程》和《亿级流量下的分布式限流解决方案》,都是面试必备的资料。
最后,如果你觉得这篇文章对你有帮助,别忘了点个赞,给个在看和转发,让更多的人看到,一起学习,一起进步!
Spring源码系列-BeanPostProcessor与BeanFactoryPostProcessor
在Spring框架中,战胜主力指标源码BeanPostProcessor与BeanFactoryPostProcessor各自承担着不同的职责,它们在IoC容器的工作流程中起着关键作用。
BeanFactoryPostProcessor作用于BeanDefinition阶段,对容器中Bean的定义进行处理。这个过程发生在BeanFactory初始化时,对BeanDefinition进行修改或增强,提供了一种在不修改源代码的情况下定制Bean的机制。相比之下,BeanPostProcessor则在Bean实例化之后生效,对已经创建的Bean对象进行进一步处理或替换,提供了更晚、更灵活的扩展点。
以制造杯子为例,BeanFactoryPostProcessor相当于在选择材料和形状阶段进行定制,而BeanPostProcessor则在杯子制造完成后,进行诸如加花纹、抛光等深加工。
在Spring框架中,BeanPostProcessor的使用场景较为广泛,尤其在实现AOP(面向切面编程)时,通过使用代理类替换原始Bean,实现如日志记录、事务管理等功能。
此外,容器在启动后,还会进行消息源初始化、广播器初始化及监听器初始化,为Bean实例化做好准备。完成这些准备工作后,容器会调用registerBeanPostProcessors方法注册BeanPostProcessor,对已创建的Bean进行进一步处理。同时,初始化消息源、广播器和监听器,熊猫视频完整源码为后续事件处理做好基础。
总结,BeanFactoryPostProcessor与BeanPostProcessor在Spring IoC容器中的作用各有侧重。前者侧重于对BeanDefinition的定制,后者则是在Bean实例化后的进一步加工,两者共同为构建灵活、可扩展的IoC容器提供了强大的支持。
在深入分析Spring框架的源码时,我们发现refresh()方法的实现中包含了对BeanFactoryPostProcessor和BeanPostProcessor的注册与处理。这些处理步骤确保了容器能够在启动时对Bean进行正确的配置和初始化。
文章中通过一个例子展示了如何使用BeanFactoryPostProcessor替换已注册Bean的实现,以及对其源码的分析。通过例子和源码的结合,读者能够更直观地理解这些后置处理器在Spring框架中的应用和工作原理。
@Import({ AutoConfigurationImportSelector.class})
ï¼2ï¼@Import({ AutoConfigurationImportSelector.class})ï¼å°AutoConfigurationImportSelectorè¿ä¸ªç±»å¯¼å ¥å°spring容å¨ä¸ï¼AutoConfigurationImportSelectorå¯ä»¥å¸®å©springbootåºç¨å°ææ符åæ¡ä»¶ç@Configurationé ç½®é½å è½½å°å½åSpringBootå建并使ç¨çIoC容å¨(ApplicationContext)ä¸
继ç»ç 究AutoConfigurationImportSelectorè¿ä¸ªç±»ï¼éè¿æºç åæè¿ä¸ªç±»ä¸æ¯éè¿selectImportsè¿ä¸ªæ¹æ³åè¯springbooté½éè¦å¯¼å ¥é£äºç»ä»¶ï¼
![image-](./images/image-.png)
æ·±å ¥ç 究loadMetadataæ¹æ³
![image-](./images/image-.png)
æ·±å ¥getCandidateConfigurationsæ¹æ³
个æ¹æ³ä¸æä¸ä¸ªéè¦æ¹æ³loadFactoryNamesï¼è¿ä¸ªæ¹æ³æ¯è®©SpringFactoryLoaderå»å è½½ä¸äºç»ä»¶çååã
![image-](./images/image-.png)
继ç»ç¹å¼loadFactoryæ¹æ³
```java
public static ListloadFactoryNames(Class factoryClass, @Nullable ClassLoaderclassLoader) {
//è·ååºå ¥çé®
String factoryClassName = factoryClass.getName();
return(List)loadSpringFactories(classLoader).getOrDefault(factoryClassName,Collections.emptyList());
}
private static Map>loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap result =(MultiValueMap)cache.get(classLoader);
if (result != null) {
return result;
} else {
try {
//å¦æç±»å è½½å¨ä¸ä¸ºnullï¼åå 载类路å¾ä¸spring.factoriesæ件ï¼å°å ¶ä¸è®¾ç½®çé 置类çå ¨è·¯å¾ä¿¡æ¯å°è£ 为Enumeration类对象
Enumeration urls =classLoader != null ?classLoader.getResources("META-INF/spring.factories") :ClassLoader.getSystemResources("META-INF/spring.factories");
LinkedMultiValueMap result =new LinkedMultiValueMap();
//循ç¯Enumeration类对象ï¼æ ¹æ®ç¸åºçèç¹ä¿¡æ¯çæProperties对象ï¼éè¿ä¼ å ¥çé®è·åå¼ï¼å¨å°å¼åå²ä¸ºä¸ä¸ªä¸ªå°çå符串转å为Arrayï¼æ¹æ³resultéåä¸
while(urls.hasMoreElements()) {
URL url =(URL)urls.nextElement();
UrlResource resource = newUrlResource(url);
Properties properties =PropertiesLoaderUtils.loadProperties(resource);
Iterator var6 =properties.entrySet().iterator();
while(var6.hasNext()) {
Entry entry= (Entry)var6.next();
String factoryClassName= ((String)entry.getKey()).trim();
String[] var9 =StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
int var =var9.length;
for(int var = 0;var < var; ++var) {
String factoryName= var9[var];
result.add(factoryClassName, factoryName.trim());
}
}
}
cache.put(classLoader, result);
return result;
```
ä¼å»è¯»åä¸ä¸ªsprin g.factoriesçæ件ï¼è¯»åä¸å°ä¼è¡¨è¿ä¸ªé误ï¼æ们继ç»æ ¹æ®ä¼çå°ï¼æç»è·¯å¾çé¿è¿æ ·ï¼èè¿ä¸ªæ¯springæä¾çä¸ä¸ªå·¥å ·ç±»
```java
public final class SpringFactoriesLoader {
public static final String FACTORIES_RESOURCE_LOCATION ="META-INF/spring.factories";
}
```
å®å ¶å®æ¯å»å è½½ä¸ä¸ªå¤é¨çæ件ï¼èè¿æ件æ¯å¨
![image-](./images/image-.png)
![image-](./images/image-.png)
@EnableAutoConfigurationå°±æ¯ä»classpathä¸æ寻META-INF/spring.factoriesé ç½®æ件ï¼å¹¶å°å ¶ä¸org.springframework.boot.autoconfigure.EnableutoConfiguration对åºçé 置项éè¿åå°ï¼Java Refletionï¼å®ä¾å为对åºçæ 注äº@ConfigurationçJavaConfigå½¢å¼çé 置类ï¼å¹¶å è½½å°IOC容å¨ä¸
以ååç项ç®ä¸ºä¾ï¼å¨é¡¹ç®ä¸å å ¥äºWebç¯å¢ä¾èµå¯å¨å¨ï¼å¯¹åºçWebMvcAutoConfigurationèªå¨é 置类就ä¼çæï¼æå¼è¯¥èªå¨é 置类ä¼åç°ï¼å¨è¯¥é 置类ä¸éè¿å ¨æ³¨è§£é 置类çæ¹å¼å¯¹Spring MVCè¿è¡æéç¯å¢è¿è¡äºé»è®¤é ç½®ï¼å æ¬é»è®¤åç¼ãé»è®¤åç¼ãè§å¾è§£æå¨ãMVCæ ¡éªå¨çãèè¿äºèªå¨é 置类çæ¬è´¨æ¯ä¼ ç»Spring MVCæ¡æ¶ä¸å¯¹åºçXMLé ç½®æ件ï¼åªä¸è¿å¨Spring Bootä¸ä»¥èªå¨é 置类çå½¢å¼è¿è¡äºé¢å é ç½®ãå æ¤ï¼å¨Spring Boot项ç®ä¸å å ¥ç¸å ³ä¾èµå¯å¨å¨åï¼åºæ¬ä¸ä¸éè¦ä»»ä½é 置就å¯ä»¥è¿è¡ç¨åºï¼å½ç¶ï¼æ们ä¹å¯ä»¥å¯¹è¿äºèªå¨é 置类ä¸é»è®¤çé ç½®è¿è¡æ´æ¹
**æ»ç»
**å æ¤springbootåºå±å®ç°èªå¨é ç½®çæ¥éª¤æ¯ï¼
1. springbootåºç¨å¯å¨ï¼
2. @SpringBootApplicationèµ·ä½ç¨ï¼
3. @EnableAutoConfigurationï¼
4. @AutoConfigurationPackageï¼è¿ä¸ªç»å注解主è¦æ¯@Import(AutoConfigurationPackages.Registrar.class)ï¼å®éè¿å°Registrarç±»å¯¼å ¥å°å®¹å¨ä¸ï¼èRegistrarç±»ä½ç¨æ¯æ«æ主é 置类å级ç®å½ä»¥ååå ï¼å¹¶å°ç¸åºçç»ä»¶å¯¼å ¥å°springbootå建管çç容å¨ä¸ï¼
5.
@Import(AutoConfigurationImportSelector.class)ï¼å®éè¿å°AutoConfigurationImportSelectorç±»å¯¼å ¥å°å®¹å¨ä¸ï¼AutoConfigurationImportSelectorç±»ä½ç¨æ¯éè¿selectImportsæ¹æ³æ§è¡çè¿ç¨ä¸ï¼ä¼ä½¿ç¨å é¨å·¥å ·ç±»SpringFactoriesLoaderï¼æ¥æ¾classpathä¸ææjarå ä¸çMETA-INF/spring.factoriesè¿è¡å è½½ï¼å®ç°å°é 置类信æ¯äº¤ç»SpringFactoryå è½½å¨è¿è¡ä¸ç³»åç容å¨å建è¿ç¨
åå¦äºæå¾æè²çãJavaå·¥ç¨å¸é«èªè®ç»è¥ãï¼çå°åå¦å°çç¹å°±åçäºãå¸ææå¾è½ç»ææ¨å°æ³å»çå ¬å¸ï¼ç®æ ï¼åèï¼ï¼
Spring源码- Spring IoC容器启动之refresh方法
在注册阶段,AnnotationConfigApplicationContext构造方法中的第一个方法被分析过。接下来,我们关注第二个方法:register(componentClasses)。在使用XML配置方式时,通过new ClassPathXmlApplicationContext("classpath:spring.xml")来创建实例,其中需要指定xml配置文件路径。使用注解方式时,也需要为ApplicationContext提供起始配置源头,这里使用配置类代替xml配置文件,按照配置类中的注解(如@ComponentScan、@Import、@Bean)解析并注入Bean到IoC容器。
通过配置类,Spring解析注解实现Bean的注入。使用@Configuration注解定义的配置类相当于xml配置文件,但目前Spring推荐使用注解方式,xml配置的使用概率正在降低。
register(componentClasses)方法的核心逻辑在AnnotatedBeanDefinitionReader#doRegisterBean中,将传入的触动精灵滑块源码配置类解析为BeanDefinition并注册到IoC容器。ConfigurationClassPostProcessor这个BeanFactory后置处理器在IoC初始化时,获取配置类的BeanDefinition集合,开始解析。
真正启动IoC容器的流程在refresh()方法中,这是了解IoC容器启动流程的关键步骤。refresh方法在AbstractApplicationContext中定义,采用模板模式,提供IoC初始化流程的基本实现,子类可以扩展。
下面分析refresh()方法的每个步骤,以了解IoC容器的启动流程。
prepareRefresh方法主要在refresh执行前进行准备工作,如设置Context的启动时间、状态,以及扩展系统属性相关。
initPropertySources()方法主要用于扩展配置来源,如网络、物理文件、数据库等加载配置信息。StandardEnvironment默认只提供加载系统变量和应用变量的功能,用于子类扩展。
❝initPropertySources方法常见扩展场景包括:❞
getEnvironment().validateRequiredProperties()确保设置的必要属性在环境中存在,否则抛出异常终止应用。
BeanFactory是Spring的基本IoC容器,ApplicationContext包装了BeanFactory,提供更智能、更便捷的功能。ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();获取的BeanFactory是IoC容器初始化工作的基础。
上面获取的BeanFactory还不能直接使用,需要填充必要的配置信息。至此,IoC容器的启动流程基本完成。
这里对IoC启动流程有个大致、直观的印象。主要步骤包括:准备阶段、配置来源扩展、初始化BeanFactory、填充配置、解析配置类、注册Bean、实例化BeanPostProcessor、初始化国际化和事件机制、以及创建内嵌Servlet容器(在SpringBoot中实现)。这些步骤确保了IoC容器顺利启动并管理Bean。
springçç»ä»¶åä½ç¨(springclouç»ä»¶)
ç®è¦è¯´æspringçä¸¤ä¸ªæ ¸å¿åè½åå ¶ä½ç¨
springæ¡æ¶æ¯ä¸ä¸ªè½»é级çå¼æºä»ä¼æ¡æ¶ï¼æ¯ä¸ä¸ªIOCåAOP容å¨ãå®æ¯ä½ä¾µå ¥å¼è®¾è®¡ï¼ç¬ç«äºåç§åºç¨æå¡å¨ï¼
ä¾èµæ³¨å ¥çç¹ç¹å°ç»ä»¶å ³ç³»éæåï¼éä½è¦å度
æ§å¶å转ï¼IOCï¼ï¼ç¨æ¥éä½ç¨åºä»£ç ä¹é´çè¦å度ï¼ä½¿æ´ä¸ªç¨åºä½ç³»ç»ææ´å çµæ´»ï¼åæ¶å°ç±»çå建åä¾èµå ³ç³»åå¨é ç½®æ件éï¼ç±é ç½®æä»¶æ³¨å ¥ï¼è¾¾å°æ¾è¦åçææã
DIï¼ä¾èµæ³¨å ¥ï¼
设å¼æ³¨å ¥ï¼åºå±å®ç°setæ¹æ³èµå¼ã
使ç¨æé å¨æ³¨å ¥ï¼ç½©å³åºå±å®ç°æé æ¹æ³æ³¨å ¥ï¼æ ¹æ®beanä¸çåæ°ç±»åååæ°æ°éï¼å¯»æ¾å¯¹åºçæé æ¹æ³ã
èªå¨è£ é ï¼ä¸è½èªå¨è£ é æè°çç®åç±»åå æ¬åºæ¬ç±»åï¼å符串åéåç±»é常ç¨æ¥èªå¨è£ é 对象
æç §å称æ¥èªå¨è£ é åºå±å®ç°æ¯setæ¹æ³
æç §ç±»åæ¥èªå¨è£ é åºå±å®ç°æ¯setæ¹æ³
2.é¢ååé¢ç¼ç¨ï¼AOPï¼
æ主è¦çä½ç¨ï¼å¯ä»¥å¨ä¸ä¿®æ¹æºä»£ç çæ åµä¸ï¼ç»ç®æ æ¹æ³å¨ææ·»å åè½
ä¸å¡é»è¾å°±ä¸å¿çå¤çå®é éæ±ï¼éç¨çå¢å¼ºåè½ç¬ç«åºæ¥ãå°å®å ¨äºå¡çç¨åºé»è¾ç¸å¯¹ç¬ç«çåè½æ½ååºæ¥ï¼å©ç¨Springçé ç½®æ件å°è¿äºåè½æè¿å»ï¼å®ç°äºæç §åé¢ç¼ç¨ï¼æé«äºå¤ç¨æ§ã
åç§å¢å¼ºæ¹å¼ï¼
åç½®å¢å¼ºï¼å¨æ ¸å¿åè½ä¹åæ§è¡çé¢å¤åè½
åç½®å¢å¼ºï¼å¨æ ¸ç©ææ å¿åè½ä¹åæ§è¡çé¢å¤åè½
å¼å¸¸å¢å¼ºï¼å¨æ ¸å¿åè½åçå¼å¸¸æ¶æ§è¡çé¢å¤åè½
ç¯ç»å¢å¼ºï¼å¨æ ¸å¿åè½ä¹å以åä¹åæ§è¡çé¢å¤åè½
springå å«åªäºç»ä»¶
Springæ¡æ¶æ¯ä¸ä¸ªåå±æ¶æï¼ç±7个å®ä¹è¯å¥½ç模åç»æè¢å¤ãSpring模åæ建å¨æ ¸å¿å®¹å¨ä¹ä¸ï¼æ ¸å¿å®¹å¨ç«å®´å®ä¹äºå建ãé ç½®å管çbeançæ¹å¼ï¼ç»æSpringæ¡æ¶çæ¯ä¸ªæ¨¡åï¼æç»ä»¶ï¼é½å¯ä»¥åç¬åå纤æ¹å¨ï¼æè ä¸å ¶ä»ä¸ä¸ªæå¤ä¸ªæ¨¡åèåå®ç°ã
SpringMVC主è¦ç»ä»¶è¯´æ1ãå端æ§å¶å¨DispatcherServletï¼ä¸éè¦å¼åï¼ç±æ¡æ¶æä¾ãæ ¸å¿ãï¼
DispatcherServletæ¯SpringMVCçå ¥å£å½æ°ãæ¥æ¶è¯·æ±ï¼ååºç»æï¼ç¸å½äºè½¬åå¨ç¢§ç®ï¼ä¸å¤®å¤çå¨ãæäºDispatcherServletï¼å¯ä»¥å¤§å¤§åå°å ¶å®ç»ä»¶ä¹é´çè¦å度ã
ç¨æ·è¯·æ±å°è¾¾å端æ§å¶å¨ï¼å°±ç¸å½äºmvc模å¼ä¸çcï¼DispatcherServletæ¯æ´ä¸ªæµç¨æ§å¶çä¸å¿ï¼ç±å®è°ç¨å ¶å®ç»ä»¶æ¥å¤çç¨æ·ç请æ±ã
2ãå¤çå¨æ å°å¨HandlerMapping(ä¸éè¦å¼åï¼ç±æ¡æ¶æä¾)
HandlerMappingè´è´£æ ¹æ®ç¨æ·è¯·æ±ï¼URLï¼ï¼æ¾å°ç¸åºçHandlerå³å¤çå¨ï¼Controllerï¼ï¼SpringMVCæä¾äºä¸åæ å°å¨å®ç°çä¸åæ å°æ¹å¼ï¼ä¾å¦ï¼é ç½®æ件æ¹å¼ï¼å®ç°æ¥å£æ¹å¼ï¼æ³¨è§£æ¹å¼çã
3ãå¤çå¨éé å¨HandlerAdapter(ä¸éè¦å¼åï¼ç±æ¡æ¶æä¾)
æç §ç¹å®è§åï¼HandlerAdapterè¦æ±çè§åï¼å»æ§è¡Handlerï¼éè¿HandlerAdapter对å¤çå¨è¿è¡æ§è¡ï¼è¿æ¯éé å¨æ¨¡å¼çåºç¨ï¼éè¿æ©å±éé å¨å¯ä»¥å¯¹æ´å¤ç±»åçå¤çå¨è¿è¡å¤çã
4ãå¤çå¨Handler(éè¦å·¥ç¨å¸å¼å)
Handleræ¯ç»§DispatcherServletå端æ§å¶å¨çå端æ§å¶å¨ï¼å¨DispatcherServletçæ§å¶ä¸ï¼Handlerå¯¹å ·ä½çç¨æ·è¯·æ±è¿è¡å¤çãç±äºHandleræ¶åå°å ·ä½çç¨æ·ä¸å¡è¯·æ±ï¼æ以ä¸è¬æ åµä¸éè¦å·¥ç¨å¸æ ¹æ®ä¸å¡éæ±æ¥å¼åHandlerã
5ãè§å¾è§£æå¨ViewResolver(ä¸éè¦å¼åï¼ç±æ¡æ¶æä¾)
ä½ç¨ï¼è¿è¡è§å¾è§£æï¼æ ¹æ®é»è¾è§å¾å解ææçæ£çè§å¾ï¼Viewï¼ï¼ViewResolverè´è´£å°å¤çç»æçæViewè§å¾ãé¦å ï¼æ ¹æ®é»è¾è§å¾å解ææç©çè§å¾åï¼å³å ·ä½ç页é¢å°åï¼ï¼åçæViewè§å¾å¯¹è±¡ï¼æå对Viewè¿è¡æ¸²æï¼å°å¤çç»æéè¿é¡µé¢å±ç¤ºç»ç¨æ·ã
SpringMVCæ¡æ¶æä¾äºå¾å¤çViewè§å¾ç±»åï¼å æ¬ï¼jstlViewãfreemarkerViewãpdfViewçãä¸è¬æ åµä¸ï¼éè¦éè¿é¡µé¢æ ç¾æ页æ¸é®é¢æ¨¡çææ¯ï¼å°æ¨¡åæ°æ®éè¿é¡µé¢å±ç¤ºç»ç¨æ·ï¼è¿éè¦ç±å·¥ç¨å¸æ ¹æ®ä¸æ §å·§ä¸å¡éæ±å¼åå ·ä½ç页é¢ã
6ãè§å¾View(éè¦å·¥ç¨å¸å¼å)
Viewæ¯ä¸ä¸ªæ¥å£ï¼å®ç°ç±»æå¯ä»¥æ¯æä¸åçViewç±»åï¼jspãfreemarkerãpdf...ï¼
æ»ç»ï¼å¤çå¨Handlerï¼ä¹å°±æ¯å¹³å¸¸è¯´çControlleræ§å¶å¨ï¼ä»¥åè§å¾å±Viewï¼é½æ¯éè¦èªè¡å¼åçãå ¶ä»çä¸äºç»ä»¶ï¼å¦ï¼å端æ§å¶å¨DispatcherServletãå¤çå¨æ å°å¨HandlerMappingãå¤çå¨éé å¨HandlerAdapterçé½æ¯ç±æ¡æ¶æä¾ã
spring主è¦çä½ç¨ï¼Springæ¡æ¶æ¯ä¸ºäºè§£å³ä¼ä¸åºç¨å¼åçå¤ææ§èå建çã
Springçç¨éä¸ä» ä» éäºæå¡å¨ç«¯çå¼åãä»ç®åæ§ãå¯æµè¯æ§åæ¾è¦åæ§è§åº¦èè¨ï¼ç»å¤§é¨åJavaåºç¨é½å¯ä»¥ä»Springä¸åçã使ç¨åºæ¬çJavaBean代æ¿EJBï¼å¹¶æä¾äºæ´å¤çä¼ä¸åºç¨åè½ã
æ©å±èµæ
ä¼ç¹
1ãJAVAEEåºè¯¥æ´å 容æ使ç¨ã
2ãé¢å对象ç设计æ¯ä»»ä½å®ç°ææ¯ï¼æ¯å¦JAVAEEï¼é½éè¦ã
3ãé¢åæ¥å£ç¼ç¨ï¼èä¸æ¯é对类ç¼ç¨ãSpringå°ä½¿ç¨æ¥å£çå¤æ度éä½å°é¶ãï¼é¢åæ¥å£ç¼ç¨æåªäºå¤æ度ï¼
4ã代ç åºè¯¥æäºæµè¯ãSpringæ¡æ¶ä¼å¸®å©ä½ ï¼ä½¿ä»£ç çæµè¯å¤è¡¡æ´å ç®åã
5ãJavaBeanæä¾äºåºç¨ç¨åºé ç½®çæ好æ¹æ³ã
6ãå¨Javaä¸ï¼å·²æ£æ¥å¼å¸¸ï¼Checkedexceptionï¼è¢«è¿åº¦ä½¿ç¨ãæ¡æ¶ä¸åºè¯¥è¿«ä½¿ä½ ææ碧è·ä¸æè´ºåè½æ¢å¤çå¼å¸¸ã
åèèµææ¥æºï¼ç¾åº¦ç¾ç§-springæ¡æ¶
什么是AOP、IOC他们的作用是什么?
什么是IoC
Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”,那我们来深入分析一下:
控制是什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。
为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。
IoC能做什么
IoC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。
其实IoC对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC容器来创建并注入它所需要的资源了。
IoC和DI
DI—Dependency Injection,即“依赖注入”:是组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。
注:如果想要更加深入的了解IoC和DI,请参考大师级人物Martin Fowler的一篇经典文章《Inversion of Control Containers and the Dependency Injection pattern》,原文地址:/articles/injection.html。
AOP:面向切面编程
什么是AOP:
概念:在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。(百度百科)
简单的说:就是将程序中重复的代码抽取出来,在需要执行的时候,使用动态代理的技术,在不修改源码的基础上,对我们的已有方法进行增强。
AOP的作用和优势:
作用:从定义中来看,就是为了在程序运行期间,不修改源码对已有方法进行增强。
优势:减少重复代码 提交了开发效率 维护方便
实现方式: 就是动态代理的技术
具体的作用:实现事务的控制 日志 和 安全模块
想系统的学习编程可以来我这看看,希望对您有所帮助!~
ioc是什么意思
IOC是控制反转的缩写。详细解释如下:
一、IOC的基本含义
IOC作为控制反转的缩写,是软件工程中一个重要的概念。在面向对象编程中,IOC思想强调的是将传统程序中由代码直接控制的流程,转变为通过配置文件或外部服务来控制,从而使得应用程序的配置和依赖性规范与实际的应用程序代码分开。这样,当应用需要进行变更或调整时,只需要更改配置文件,而无需更改实际的应用程序代码。IOC大大增强了软件系统的可维护性和灵活性。
二、IOC的重要性
在传统的程序设计中,程序的流程通常由程序本身的代码控制。而随着软件系统的复杂性和规模的扩大,这种方式的缺点逐渐显现。一旦系统需要改变流程,就意味着需要修改源代码,这不仅增加了维护的难度,也降低了系统的灵活性。而IOC的出现解决了这一问题,它通过将程序的依赖关系外部化,使得程序流程的控制权发生了反转。这样,程序就可以更加专注于自身的业务逻辑,而无需关心依赖关系的创建和管理。
三、IOC的应用场景
IOC在软件系统中有着广泛的应用场景。特别是在依赖注入技术中,IOC的思想得到了充分的体现。在依赖注入技术中,对象的创建和对象间的相互调用关系被外部化,并由IOC容器来管理。通过这种方式,开发者可以更加专注于业务逻辑的实现,而无需关心对象的创建和配置细节。这种解耦的设计方式大大提高了软件系统的可维护性和可扩展性。
综上所述,IOC作为控制反转的缩写,在软件工程中具有重要意义。它通过改变程序流程的控制方式,使得软件系统的配置和依赖关系与实际的应用程序代码分开,从而提高了软件系统的可维护性和灵活性。
Spring IoC源码深度剖析
Spring IoC容器初始化深度剖析
Spring IoC容器是Spring的核心组件,主要负责对象管理和依赖关系管理。容器体系丰富多样,如BeanFactory作为顶层容器,它定义了所有IoC容器的基本原则,而ApplicationContext及其子类如ClassPathXmlApplicationContext和AnnotationConfigApplicationContext则提供了额外功能。Spring IoC容器的初始化流程关键在AbstractApplicationContext的refresh方法中。 1.1 初始化关键点 通过创建特定类LagouBean并设置断点,我们发现Bean的创建在未设置延迟加载时,发生在容器初始化过程中。构造函数调用、InitializingBean的afterPropertiesSet方法以及BeanFactoryPostProcessor和BeanPostProcessor的初始化和调用,都在refresh方法的不同步骤中发生。 1.2 主体流程概览 Spring IoC容器初始化的主体流程主要集中在AbstractApplicationContext的refresh方法,涉及Bean对象创建、构造函数调用、初始化方法执行和处理器调用等步骤。 1.3 深度剖析 分析发现,延迟加载机制使得懒加载的bean在第一次调用getBean时才进行初始化。而对于非懒加载bean,它们在容器初始化阶段已经完成并缓存。Spring处理循环依赖的方法依赖于构造器调用的顺序规则,不支持原型bean的循环依赖,而对单例bean则通过setXxx或@Autowired方法提前暴露对象来避免循环依赖。2024-12-29 00:48
2024-12-29 00:37
2024-12-29 00:06
2024-12-28 23:50
2024-12-28 23:41
2024-12-28 23:02
2024-12-28 22:30
2024-12-28 22:20