皮皮网

【任天堂html5源码】【msgrcv源码】【concurenthashmap源码】mybean框架源码_框架源代码

来源:寄售抢拍系统源码 时间:2024-12-23 00:01:16

1.spring—AOP与事务
2.@Lazy注解源码分析
3.6. Spring源码篇之FactoryBean
4.如何使用NetBeans IDE创建简单的Web应用程序

mybean框架源码_框架源代码

spring—AOP与事务

        title: spring——AOP与事务.md

        date: -- ::

        categories: [Spring]

        tags: [AOP,框架框架事务]

        toc: true

        先列出源码中比较重点的几个类:

        1、<aop:before method="before" pointcut-ref="myMethods"/>包装成一个advisor

        2、AspectJAwareAdvisorAutoProxyCreator,当实例化所有bean都会执行到AspectJAwareAdvisorAutoProxyCreatorç±»

        它会检测bean是否advisor以及advice存在,如果有就说明这个bean有切面,有切面那么就会生成代理

        3、jdk的代理,bean里面的所有advisor加入到proxyFactory。

        4、jdkDynamicProxy invoke,拿到bean里面的所有Interceptor,会循环proxyFactory里面的所有advisor

        里面有advice,里面的advice有两种类型,要么是advice,要么是MethodInterceptor类型的

        5、当代理对象调用方式,是一个MethodInterceptor类型的类的链式调用过程,直到容器的大小和索引一致的时候调用JoinPoint目标方法

        before:this.advice.before(),invocation.processd();

        装配参数,切面里面before方法的method对象,method.getParamterTypes()[0]

        最终会把advice封装成MethodInterceptor类型的对象

        程序执行的某个特定位置:如类开始初始化前、类初始化后、类某个方法调用前、调用后、方法抛出异常后。一个类或一段程序代码拥有一些具有边界性质的特定点,这些点中的特定点就称为“连接点”。Spring仅支持方法的连接点,即仅能在方法调用前、方法调用后、方法抛出异常时以及方法调用前后这些程序执行点织入增强。连接点由两个信息确定:第一是用方法表示的程序执行点;第二是用相对点表示的方位。

        每个程序类都拥有多个连接点,如一个拥有两个方法的类,这两个方法都是连接点,即连接点是程序类中客观存在的事物。AOP通过“切点”定位特定的连接点。连接点相当于数据库中的记录,而切点相当于查询条件。切点和连接点不是一对一的关系,一个切点可以匹配多个连接点。在Spring中,切点通过org.springframework.aop.Pointcut接口进行描述,它使用类和方法作为连接点的查询条件,Spring AOP的规则解析引擎负责切点所设定的查询条件,找到对应的连接点。其实确切地说,不能称之为查询连接点,因为连接点是方法执行前、执行后等包括方位信息的具体程序执行点,而切点只定位到某个方法上,所以如果希望定位到具体连接点上,还需要提供方位信息。

        增强是织入到目标类连接点上的一段程序代码,在Spring中,增强除用于描述一段程序代码外,还拥有另一个和连接点相关的信息,这便是执行点的方位。结合执行点方位信息和切点信息,我们就可以找到特定的连接点。

        增强逻辑的织入目标类。如果没有AOP,目标业务类需要自己实现所有逻辑,而在AOP的帮助下,目标业务类只实现那些非横切逻辑的程序逻辑,而性能监视和事务管理等这些横切逻辑则可以使用AOP动态织入到特定的连接点上。

        引介是一种特殊的增强,它为类添加一些属性和方法。这样,即使一个业务类原本没有实现某个接口,通过AOP的引介功能,我们可以动态地为该业务类添加接口的实现逻辑,让业务类成为这个接口的实现类。

        织入是将增强添加对目标类具体连接点上的过程。AOP像一台织布机,将目标类、增强或引介通过AOP这台织布机天衣无缝地编织到一起。根据不同的实现技术,AOP有三种织入的方式:

        a、编译期织入,这要求使用特殊的Java编译器。

        b、类装载期织入,这要求使用特殊的类装载器。

        c、动态代理织入,在运行期为目标类添加增强生成子类的方式。

        Spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入。

        一个类被AOP织入增强后,就产出了一个结果类,它是融合了原类和增强逻辑的代理类。根据不同的代理方式,代理类既可能是和原类具有相同接口的类,也可能就是原类的子类,所以我们可以采用调用原类相同的方式调用代理类。

        切面由切点和增强(引介)组成,它既包括了横切逻辑的定义,也包括了连接点的定义,Spring AOP就是负责实施切面的框架,它将切面所定义的横切逻辑织入到切面所指定的连接点中。

        advisor: pointCut advice

        一类功能的增强

        around方法里面代码切面

        事务切面

        缓存切面

        日志切面

        事务(Transaction),一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作;这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行;事务是一组不可再分割的操作集合(工作逻辑单元)。

        大致流程形如

        数据库事务拥有几大特性:

        事务的四大特性:

        事务是数据库的逻辑工作单位,事务中包含的各操作要么都做,要么都不做

        事 务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。因此当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态。如果数据库系统 运行中发生故障,有些事务尚未完成就被迫中断,这些未完成事务对数据库所做的修改有一部分已写入物理数据库,这时数据库就处于一种不正确的状态,或者说是 不一致的状态。

        一个事务的执行不能其它事务干扰。即一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务之间不能互相干扰。

        也称永久性,指一个事务一旦提交,它对数据库中的数据的改变就应该是永久性的。接下来的其它操作或故障不应该对其执行结果有任何影响。

        个人理解,事务在Spring中是借助AOP技术来实现的,可以作为AOP中的一个事务切面。spring源码对事务的处理逻辑,自己研究吧!

        ORM框架中以Mybatis为例,事务处理就是用到了一个类Transaction,部分源码如下

        可以看出Transaction管理的就是一个connection,而connection我们很清楚是与用户会话挂钩的。

        那么关系就是Transaction 管理Connection ,而connection与 用户session一对一存在。

        在springBoot中,只需要加入POM就可以了,配合注解使用即可。

        接下来就是事务的控制了。

        首先事务有几大传播属性:

        其中最常见的,用得最多就 PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW、 PROPAGATION_NESTED 这三种。事务的传播属性是 spring 特有的,是 spring 用来控制方法事务的一种手段,说直白点就是用来控制方法是否使用同一事务的一种属性,以及按照什么规则回滚的一种手段。

        下面用代码演示这三种属性的机制:

        事务的默认属性就是required,通过Transactional.java中的Propagation propagation() default Propagation.REQUIRED; 可以看出。

        这种情况就是事务1,事务2 都加入到了事务0中。不管是1,2哪个事务抛出异常,事务0都会回滚。数据添加会失败。

        这种情况就是:

        事务0(required) {

        ​ 事务1 (REQUIRES_NEW)

        ​ 事务2

        }

        此时。

        情况a:

        1、如果只是事务2出现了异常,那么事务1会提交,事务2加入到事务0中会回滚。

        2、如果只是事务1出现了异常,那么事务1会回滚,向上层事务0抛异常,事务2会加入到事务0中,这时都会回滚。

        情况b:

        如果事务1,事务2都是REQUIRES_NEW传播属性。那么结果就是:

        1、如果事务1,抛出了异常,那么事务2是不会执行的,那么事务0必然回滚。

        2、如果事务2,抛出异常,那么事务1会提交,表中会有数据。事务2有异常回滚并抛出,事务0回滚。

        NESTED属性其实就是创建了回滚点,有异常时,会回滚到指定的回滚点。

        在这通过代码测试,出现一种情况是,无论事务1,事务2哪个有异常,数据都不会插入成功,原因是,不论是事务1还是事务2都会向事务0抛出异常,事务0捕获到异常后,执行rollback()方法,这就操作成了,事务的全部回滚。

        如果想要事务1和事务2 想要根据自己的回滚点回滚,那么事务0必须自己处理异常,不让spring捕获到这个异常,那么就满足了。把代码改成这种:

        Jack大佬提供了,伪代码分析法。

        按照Spring源码的事务处理逻辑,伪代码大致为:

@Lazy注解源码分析

       @Lazy注解是Spring框架3.0版本后引入的,用于控制bean的源码源代懒加载行为,主要用途是框架框架延迟依赖注入的初始化。默认情况下,源码源代当ApplicationContext启动和刷新时,框架框架所有的源码源代任天堂html5源码单例bean会被立即初始化。然而,框架框架有时可能希望某些bean在首次使用时才被初始化。源码源代实现这一目标的框架框架方法是将@Lazy注解应用到bean或注入点,如@Autowired,源码源代以创建懒解析代理,框架框架从而实现延迟注入。源码源代

       @Lazy注解对@Bean、框架框架@Component或@Bean定义的源码源代msgrcv源码bean的延迟初始化特别有用。当用在@Configuration类上时,框架框架它会影响该配置中的所有@Bean定义。通过在启动类入口使用AnnotationConfigApplicationContext并提供MyConfiguration组件类,从MyService bean获取并调用其show方法,可以观察到MyBean在首次被请求时才被初始化,而MyService的初始化则立即进行。MyBean类的构造函数在被调用时打印"MyBean的构造函数被调用了!",show方法则打印"hello world!"。MyService类通过@Autowired注入MyBean,由于在注入点上添加了@Lazy注解,myBean的实际注入被延迟,直到首次尝试访问它时。

       源码分析表明,concurenthashmap源码在启动类构造函数中,执行了三个步骤以初始化实例。在refresh方法中,重点关注了finishBeanFactoryInitialization方法,该方法会对所有剩余非懒加载的单例bean对象进行初始化,除非它们显式标记为懒加载。在preInstantiateSingletons方法中,确保所有非懒加载的单例bean在容器启动时被初始化,除非它们被标记为懒加载。这使得@Lazy注解对于希望推迟bean初始化的场景非常有用。

       在getBean()方法中,通过doGetBean方法执行了创建bean的过程。在doCreateBean方法中,源码 tree对bean的属性进行注入。在populateBean方法中,如果一个属性被标记为@Autowired,并且与@Lazy结合使用,那么实际的懒加载逻辑会在其他部分处理,特别是通过AutowiredAnnotationBeanPostProcessor。在resolveFieldValue方法中,解析@Autowired字段的值,并确定应为目标字段注入哪个bean。在resolveDependency方法中,如果依赖关系标记为懒加载,它将返回一个懒加载代理,只有在应用程序真正访问该依赖时,introspector源码实际的bean才会被初始化。

       总结而言,@Lazy注解提供了在Spring容器中控制bean初始化的灵活性,允许开发者根据需要延迟依赖注入的初始化,从而优化应用性能和资源管理。在实践过程中,注意合理使用@Lazy注解,确保代码的清晰性和可维护性。同时,理解Spring容器在bean初始化过程中的工作原理,可以帮助开发者更有效地利用该框架的特性,实现更高效的应用开发。

6. Spring源码篇之FactoryBean

       FactoryBean是Spring提供的一个功能强大的小型工厂,用于灵活创建所需Bean。在框架与Spring整合时,尤其是Mybatis-plus中,通过注解可以自动生成Spring Bean,而FactoryBean的功能正是实现批量动态生成Bean。下面详细介绍FactoryBean的源码解析。

       首先,我们来看看如何判断一个对象是否为FactoryBean。在Spring的实例化过程中,如果类实现了FactoryBean接口,则会被识别为FactoryBean。而获取FactoryBean时,通常在Bean名称前加上"&"符号。

       接下来,我们深入分析FactoryBean的接口。

       FactoryBean接口定义了如何创建Bean,包含两个主要方法:getObject和isInstance。getObject用于返回创建的Bean实例,isInstance用于判断一个对象是否由FactoryBean创建。

       SmartFactoryBean是FactoryBean的子接口,它提供了额外的特性,允许决定是否提前实例化对象。

       在实际使用中,FactoryBean的实例化过程较为关键。如果不希望立即实例化某个非懒加载单例Bean,则需要确保它未被识别为FactoryBean。例如,UserBean的实例化代码在正常情况下不会打印任何输出,表明并未实例化。而通过将UserBean实现为SmartFactoryBean,并使isEagerInit返回true,就能在控制台中观察到UserBean的实例化过程。

       获取FactoryBean创建的Bean有多种方式。通过在Bean名称前加"&",可以获取到由getObject方法生成的Bean。此外,若需要获取FactoryBean本身,则可以使用多个"&"符号,Spring会循环遍历,直至获取到实际的Bean。

       在Spring实例化完成后,通常会调用getObjectForBeanInstance方法来获取真正的Bean实例。这一过程包括了共享实例(sharedInstance)的引用和Bean名称的处理。最终,通过调用getObject方法,我们能够获取到由FactoryBean生成的实际Bean。

       以Mybatis-plus中的MapperFactoryBean为例,说明了如何在实际项目中应用FactoryBean。MapperFactoryBean是Mybatis-plus提供的一个FactoryBean,用于自动注册Mapper接口为Spring Bean。

       总结而言,FactoryBean在Spring中扮演着灵活创建和管理Bean的重要角色,尤其在需要动态生成或自定义Bean创建逻辑的场景中。通过理解其源码和使用方法,开发者可以更高效地整合各类框架与Spring,实现更为灵活和高效的系统构建。

如何使用NetBeans IDE创建简单的Web应用程序

       ã€€åœ¨æ‰§è¡Œ Web & Java EE 安装时,您可以选择安装 GlassFish 2.1 应用服务器和 6.0.x 版本的 Apache Tomcat Servlet 容器。必须安装其中一个才能学完本教程。

       ã€€ã€€è¦åˆ©ç”¨ NetBeans IDE 的 Java EE 5 功能,请使用完全符合 Java EE 5 规范的应用服务器,例如 GlassFish 2.1 UR2 应用服务器。如果使用的是其他服务器,请查阅发行说明和常见问题解答,了解已知问题和解决方法。有关支持的服务器和 Java EE 平台的详细信息,请参见发行说明。

       ã€€ã€€å¦‚果需要将项目与工作解决方案进行比较,可以下载样例应用程序。

       ã€€ã€€è®¾ç½® Web 应用程序项目

       ã€€ã€€ä»Žä¸»èœå•ä¸­é€‰æ‹©â€œæ–‡ä»¶â€>“新建项目”(Ctrl-Shift-N)。在“类别”下,选择“Java Web”。在“项目”下选择“Web 应用程序”,然后单击“下一步”。

       ã€€ã€€åœ¨æ­¥éª¤ 2 中,在“项目名称”文本框中输入 HelloWeb。

       ã€€ã€€å°†â€œé¡¹ç›®ä½ç½®â€æŒ‡å®šä¸ºè®¡ç®—机上的任意目录。在本教程中,将此目录称为 $PROJECTHOME。

       ã€€ã€€ï¼ˆå¯é€‰ï¼‰é€‰ä¸­â€œä½¿ç”¨ä¸“用文件夹存储库”复选框,并指定库文件夹的位置。有关此选项的详细信息,请参见共享项目库。

       ã€€ã€€å•å‡»â€œä¸‹ä¸€æ­¥â€ã€‚“服务器和设置”面板打开。选择要与应用程序一起使用的 Java EE 版本。

       ã€€ã€€é€‰æ‹©è¦åœ¨å…¶ä¸­éƒ¨ç½²åº”用程序的服务器。这里仅列出了已在 IDE 中注册的服务器。请注意,服务器上的上下文路径将变为 /HelloWeb(基于您在上一步中为项目指定的名称)。

       ã€€ã€€å•å‡»â€œä¸‹ä¸€æ­¥â€ã€‚在“框架”面板中,单击“完成”以创建项目。

       ã€€ã€€IDE 将创建 $PROJECTHOME/HelloWeb 项目文件夹。此项目文件夹包含所有源代码和项目 meta 数据,例如项目的 Ant 生成脚本。在 IDE 中,将打开 HelloWeb 项目。在主窗口的源代码编辑器中,将打开欢迎页 index.jsp。您可以在“文件”窗口 (Ctrl-2) 中查看项目的文件结构,在“项目”窗口 (Ctrl-1) 中查看其逻辑结构。

       ã€€ã€€åˆ›å»ºå¹¶ç¼–辑 Web 应用程序源文件

       ã€€ã€€åˆ›å»ºå¹¶ç¼–辑源文件是 IDE 所提供的最重要的功能。毕竟,这大概是您花费时间最多的工作。IDE 提供了各种工具来迎合任何开发者的个人风格,无论您是愿意手动编写所有代码,还是希望 IDE 为您生成大量代码。

       ã€€ã€€åˆ›å»º Java 包和 Java 源文件

       ã€€ã€€åœ¨â€œé¡¹ç›®â€çª—口中,展开“源包”节点。请注意,“源包”节点仅包含一个空的缺省包节点。

       ã€€ã€€å³é”®å•å‡»â€œæºåŒ…”节点,然后选择“新建”>“Java 类”。在“类名”文本框中输入 NameHandler,并在“包”组合框中键入 org.mypackage.hello。单击“完成”。请注意,将在源代码编辑器中打开新的 NameHandler.java 文件。

       ã€€ã€€åœ¨æºä»£ç ç¼–辑器中,通过在紧靠类声明的下方键入以下代码行来声明一个 String 变量。 String name;

       ã€€ã€€å°†ä»¥ä¸‹æž„造函数添加到类中: public NameHandler()

       ã€€ã€€åœ¨ NameHandler() 构造函数中添加以下代码行: name = null;

       ã€€ã€€ç”Ÿæˆ getter 和 setter 方法

       ã€€ã€€åœ¨æºä»£ç ç¼–辑器中右键单击 name 字段,然后选择“重构”>“封装字段”。将打开“封装字段”对话框,其中列出 name 字段。请注意,缺省情况下将“字段的可视性”设置为 "private",将“存取方法的可视性”设置为 "public",这表示类变量声明的访问修饰符将被指定为 private,而 getter 和 setter 方法将分别以 public 和 private 修饰符生成。

       ã€€ã€€å•å‡»â€œé‡æž„”。将为 name 字段生成 getter 和 setter 方法。类变量的修饰符将被设置为 private,而 getter 和 setter 方法将以 public 修饰符生成。

       ã€€ã€€ç¼–辑缺省的 JavaServer Pages 文件

       ã€€ã€€é€šè¿‡å•å‡»åœ¨æºä»£ç ç¼–辑器顶部显示的 "index.jsp" 文件标签以重新选中该文件。

       ã€€ã€€åœ¨ä½äºŽæºä»£ç ç¼–辑器右侧的组件面板 (Ctrl-Shift-8) 中,展开“HTML 表单”,然后将一个表单项拖至源代码编辑器中

       ã€€ã€€æ ‡è®°åŽçš„某个位置。

       ã€€ã€€å°†æ˜¾ç¤ºâ€œæ’入表单”对话框。

       ã€€ã€€è¯·æŒ‡å®šä»¥ä¸‹å€¼ï¼š

       ã€€ã€€æ“ä½œï¼šresponse.jsp

       ã€€ã€€æ–¹æ³•ï¼šGET

       ã€€ã€€åç§°ï¼šName Input Form

       ã€€ã€€å•å‡»â€œç¡®å®šâ€ã€‚将在 index.jsp 文件中添加一个 HTML 表单。

       ã€€ã€€å°†ä¸€ä¸ªæ–‡æœ¬è¾“入项拖至紧靠 标记前面的位置,然后指定以下值:

       ã€€ã€€åç§°ï¼šname

       ã€€ã€€ç±»åž‹ï¼šæ–‡æœ¬

       ã€€ã€€å•å‡»â€œç¡®å®šâ€ã€‚将在 标记之间添加一个 HTML 标记。

       ã€€ã€€å°†ä¸€ä¸ªæŒ‰é’®é¡¹æ‹–至紧靠 标记前面的位置。请指定以下值:

       ã€€ã€€æ ‡ç­¾ï¼šOK

       ã€€ã€€ç±»åž‹ï¼šæäº¤

       ã€€ã€€å•å‡»â€œç¡®å®šâ€ã€‚将在 标记之间添加一个 HTML 按钮。

       ã€€ã€€åœ¨ç´§é ç¬¬ä¸€ä¸ª 标记前面的位置键入 Enter your name:,然后将

       ã€€ã€€æ ‡è®°ä¹‹é—´çš„缺省 Hello World! 文本更改为 Entry Form。

       ã€€ã€€åˆ›å»º JavaServer Pages 文件

       ã€€ã€€åœ¨â€œé¡¹ç›®â€çª—口中,右键单击 "HelloWeb" 项目节点,然后选择“新建”> "JSP"。将打开“新建 JSP 文件”向导。将文件命名为 response,然后单击“完成”。请注意,在“项目”窗口中的 "index.jsp" 下方将显示 "response.jsp" 文件节点,并且会在源代码编辑器中打开新文件。

       ã€€ã€€åœ¨ä½äºŽæºä»£ç ç¼–辑器右侧的组件面板中,展开 "JSP",然后将一个使用 Bean 项拖至源代码编辑器中紧靠 标记下方的位置。将打开“插入使用 Bean”对话框。指定下图中显示的值。

       ã€€ã€€ID:mybean

       ã€€ã€€ç±»ï¼šorg.mypackage.hello.NameHandler

       ã€€ã€€èŒƒå›´ï¼šsession

       ã€€ã€€å•å‡»â€œç¡®å®šâ€ã€‚请注意,将在 标记的下方添加 标记。

       ã€€ã€€å°†ä¸€ä¸ªè®¾ç½® Bean 属性项从组件面板拖至紧靠 <h1> 标记前面的位置,然后单击“确定”。在出现的 标记中,删除空的 value 属性,然后将其编辑为以下代码。如果 IDE 创建了 value = "" 属性,请将其删除!否则,它会覆盖传递到 index.jsp 中的 name 的值。

       ã€€ã€€æ­£å¦‚ 文档中所述,可以通过各种方法来设置属性值。在本例中,index.jsp 页上的用户输入将成为传递至 request 对象的名称/值对。当使用 标记设置属性时,可以根据 request 对象中包含的属性名称来指定值。因此,通过将 property 设置为 name,可以检索由用户输入所指定的值。

       ã€€ã€€æ›´æ”¹ <h1> 标记之间的文本,以使其如下所示: <h1>Hello, !

       ã€€ã€€å°†ä¸€ä¸ªèŽ·å– Bean 属性项从组件面板拖放到

       ã€€ã€€æ ‡è®°ä¹‹é—´çš„逗号后面。在“插入获取 Bean 属性”对话框中指定以下值:

       ã€€ã€€Bean 名称:mybean

       ã€€ã€€å±žæ€§åç§°ï¼šname

       ã€€ã€€å•å‡»â€œç¡®å®šâ€ã€‚请注意,此时将在 <h1> 标记之间添加 <jsp:getProperty> 标记。