1.Java学习资源
2.android studio å¯ä»¥ä½¿ç¨javassistå
3.通过transmittable-thread-local源码理解线程池线程本地变量传递的原理
4.Mybatis源码剖析(懒加载原理)
Java学习资源
Java Commons Java tutorial WebService常用第三方webservice IDEEclipse Eclipse GUI Plugin Eclipse根据java代码生成UML图 Tomcat Hudson Jenkins Atlassian Bamboo TeamCity JUnit DbUnit JMockit TestNG ReportNG SLF4J Log4j Logback Log4E代码评审 guava jga Java Class Dependency Analyzer OW2Forge Rock apache Apache Commons sandbox中的项目无法直接通过maven进行依赖,必须通过svn下载源码,部署到本地maven仓库中。例如对于sandbox中的classscan项目: # 项目地址:commons.apache.org/sand... svn checkout mons/sandbox/classscan classscan cd classscan 当install带有parent的maven项目时,如果没有把parent一并install,其它项目引用时会出现 mvn install--Failed to read artifact descriptor for org.apache.maven.plugins:maven-source-plugin:jar:2.1.2 cd parent (classscan/parent) mvn clean package install -DskipTests cd ../api (classscan/api) mvn clean package install -DskipTests cd ../bcel (classscan/bcel) mvn clean package install -DskipTests 在pom.xml中添加依赖 org.apache.commons.classscan bcel 0.2-SNAPSHOT org.apache.commons.classscan api 0.2-SNAPSHOT Eclipse中Update Project,选择Force Update of Snapshots/Releases Apache HttpComponents Maven and M2Eclipse maven快速下载某个jar包依赖的开源收银app源码所有jar 经常碰到这种事情:在一些非maven工程中(由于某种原因这种工程还是手工添加依赖的),需要用到某个新的类库(假设这个类库发布在maven库中),而这个类库又间接依赖很多其他类库,如果依赖路径非常复杂的话,一个个检查手动下载是很麻烦的事。下面给出一个便捷的办法,创建一个新目录里面建一个maven pom文件, 添加需要依赖的类库: 4.0.0 com.dep.download dep-download 1.0-SNAPSHOT com.xx.xxx yy-yyy x.y.z 在这个目录下运行命令,所有跟这个类库相关的直接和间接依赖的jar包都会下载到 ./target/dependency/下 杂项 间接依赖的jar包能否直接使用 如果工程依赖A.jar,并用maven设置好依赖,同时A.jar会依赖B.jar,所以maven在下载A.jar的同时会下载B.jar,这时如果项目发现需要使用B.jar中的一些内容,在maven中不必从新设置依赖,可以在工程中直接使用。 把某个本地jar包安装到本地仓库中 mvn install:install-file -DgroupId=“edu.jiangxin” -DartifactId=”gcu” -Dversion=“1.0.0” -Dpackaging=”jar” -Dfile=“D:\CS\J2EE\lib\edu.jiangxin.gcu-1.0.0.jar” 把某个本地jar包部署到某个远程仓库中 mvn deploy:deploy-file -DgroupId=“edu.jiangxin” -DartifactId=”gcu” -Dversion=“1.0.0” -Dpackaging=”jar” -Dfile=“D:\CS\J2EE\lib\edu.jiangxin.gcu-1.0.0.jar” -Durl= yourlocalrepository:... -DrepositoryId=internal bintray bintray.com/ Ant Eclipse Color Themes MyEclipse EclEmma eCobertura JavaNCSS Clover(收费) CAP (code analysis plugin) Visual Performance Analyzer VisualVM JD(Java Decompiler) 注:不支持命令行使用,因而很难批量编译。远程调试jvm源码 jad 注:jad支持命令行方式使用,最新版本为1.5.8g,支持的class版本过低。经常出现问题:The class file version is .0 (only .3, .0 and .0 are supported)。还有一个工具uuDeJava,也是基于jad,所以估计也难以避免这个问题。 jdec JODED J Java Decompiler 注:收费软件,没有试用过 ProGuard FindBugs PMD Metric Jdepend SourceHelper Structure inFusion SourceMonitor Simian CheckStyle CCTE J-Technologies一家(收费) FORTIFY SCA(收费) coverity(收费) klocwork(收费) GProf Dot and Graphviz sikuli exe4j JBoss GlassFish Virgo Jetty cpDetector EZMorph Apache Shiro Struts Spring Hibernate iBATIS/MyBatis appfuse TopLink json neethi XML SAXON jsoup HTML Parser Java port of Mozilla charset detector(jchardet) JMX jsch * yFiles The yFiles diagramming software components are extensive class libraries that enable you to add high-quality diagramming functionality to your own software applications OpenLDAP Protobuf zip4j JFlex JavaCC sablecc Xtext antlr cglib javassist jclasslib ical4j 分词规则引擎 Drools jBPM OpenAS2 Java Native Access (JNA) mpi Java eBus JACOBA Apache POI - the Java API for Microsoft Documents iText(AGPL) aspose MVEL(Drools) OGNL(Struts) SPEL(Spring) JSP EL freemarker Velocity Auroraandroid studio å¯ä»¥ä½¿ç¨javassistå
å¼åè°è¯ç¯å¢: Ubuntu .ï¼openJdk 1.7ï¼Android Studio 1.0.2ï¼android-5.0.1_r1æºç
ç±äºASæ¯åºäºIntelliJ IDEAå¼åçï¼æ以æ¬æä¹éç¨äºIntelliJ IDEA
ä¸ãä¿®æ¹Android Studio(以ä¸ç®ç§°AS)çå åé ç½®
å 为å¨å¯¼å ¥æºç æ¶éè¦æ¶è大éå åï¼æ以å ä¿®æ¹IDEA_HOME/bin/studio.vmoptions(xçæºå¨ä¿®æ¹studio.vmoptions)ä¸-Xmså-Xmxçå¼ãææ¡£ä¸ä½¿ç¨çæ¯m, å¯èªè¡ä¿®æ¹ã
äºãé ç½®ASçJDKãSDK
å¨IDEä¸æ·»å ä¸ä¸ªæ²¡æclasspathçJDK, è¿æ ·å¯ä»¥ç¡®ä¿ä½¿ç¨æºç éçåºæ件
通过transmittable-thread-local源码理解线程池线程本地变量传递的原理
最近几周,我投入了大量的时间和精力,完成了UCloud服务和中间件迁移至阿里云的工作,因此没有空闲时间撰写文章。不过,回忆起很早之前对ThreadLocal源码的分析,其中提到了ThreadLocal存在向预先创建的线程中传递变量的局限性。恰好,疫苗接种助手源码我的一位前同事,HSBC的技术大牛,提到了团队引入了transmittable-thread-local(TTL)来解决此问题。借此机会,我深入分析了TTL源码,本文将全面分析ThreadLocal和InheritableThreadLocal的局限性,并深入探讨TTL整套框架的实现。如有对线程池和ThreadLocal不熟悉的读者,建议先阅读相关前置文章,本篇文章行文较为干硬,字数接近5万字,希望读者耐心阅读。
在Java中,没有直接的API允许子线程获取父线程的实例。获取父线程实例通常需要通过静态本地方法Thread#currentThread()。同样,剥头皮源码python为了在子线程中传递共享变量,也常采用类似的方法。然而,这种方式会导致硬编码问题,限制了方法的复用性和灵活性。为了解决这一问题,线程本地变量Thread Local应运而生,其基本原理是通过线程实例访问ThreadLocal.ThreadLocalMap来实现变量的存储与传递。
ThreadLocal与InheritableThreadLocal之间的区别主要在于控制ThreadLocal.ThreadLocalMap的创建时机和线程实例中对应的属性获取方式。通过分析源码,可以清楚地看到它们之间的联系与区别。对于不熟悉概念的读者,可以尝试通过自定义实现来理解其中的原理与关系。
ThreadLocal和InheritableThreadLocal的最大局限性在于无法为预先创建的线程实例传递变量。泛线程池Executor体系、TimerTask和ForkJoinPool等通常会预先创建线程,税源码的麦因此无法在这些场景中使用ThreadLocal和InheritableThreadLocal来传递变量。
TTL提供了更灵活的解决方案,它通过委托机制(代理模式)实现了变量的传递。委托可以基于Micrometer统计任务执行时间并上报至Prometheus,然后通过Grafana进行监控展示。此外,TTL通过字节码增强技术(使用ASM或Javassist等工具)实现了类加载时期替换Runnable、Callable等接口的实现,从而实现了无感知的增强功能。TTL还使用了模板方法模式来实现核心逻辑。
TTL框架的核心类TransmittableThreadLocal继承自InheritableThreadLocal,通过全局静态变量holder来管理所有TransmittableThreadLocal实例。holder实际上是一个InheritableThreadLocal,用于存储所有线程本地变量的映射,实现变量的全局共享。disableIgnoreNullValueSemantics属性的设置可以影响NULL值的处理方式,影响TTL实例的行为。
发射器Transmitter是TransmittableThreadLocal的一个公有静态类,提供传输TransmittableThreadLocal实例和注册当前线程变量至其他线程的功能。通过Transmitter的静态方法,可以实现捕获、重放和复原线程本地变量的功能。
TTL通过TtlRunnable类实现了任务的封装,确保在执行任务时能够捕获和传递线程本地变量。在任务执行前后,通过capture和restore方法捕获和重放变量,实现异步执行时上下文的传递。
启用TTL的Agent模块需要通过Java启动参数添加javaagent来激活字节码增强功能。TTL通过Instrumentation回调激发ClassFileTransformer,实现目标类的字节码增强,从而在执行任务时自动完成上下文的捕捉和传递。
TTL框架提供了一种高效、灵活的方式来解决线程池中线程复用时上下文传递的问题。通过委托机制和字节码增强技术,TTL实现了无入侵地提供线程本地变量传递功能。如果您在业务代码中遇到异步执行时上下文传递的问题,TTL库是一个值得考虑的解决方案。
Mybatis源码剖析(懒加载原理)
懒加载,即按需加载,旨在优化查询性能。以一个包含订单列表的User对象为例,当仅获取用户信息时,若启用懒加载模式,执行SQL不会查询订单列表。需获取订单列表时,才会发起数据库查询。实现方式包括在核心配置文件中设置或在相关映射文件中通过fetchType属性配置懒加载策略。
懒加载的配置如何加载到项目中呢?首先,这些配置保存在全局Configuration对象中,通常在解析核心配置文件的代码中实现。在settingsElement方法中,懒加载配置被保存在lazyLoadingEnabled属性中。对于resultMap标签中collection | association的fetchType属性,其配置通过解析mappers标签下的resultMap标签实现,最终调用buildResultMappingFromContext方法处理子标签。该方法结合全局配置判断是否需要执行懒加载。
懒加载的实现原理涉及动态代理。当调用代理对象的延迟加载属性方法时,如访问a.getB().getName(),代理对象会调用拦截器方法。若发现需要延迟加载,代理对象会单独发送SQL查询关联对象,加载数据后设置属性值,完成方法调用。简而言之,懒加载通过动态代理实现,拦截指定方法并执行数据加载。
深入剖析懒加载源码,会发现它涉及查询和数据处理的多步操作。查询完成后,结果集处理、列值获取、判断是否进行懒加载等步骤共同构建懒加载机制。动态代理在访问对象属性时触发,最终通过Javassist库创建代理对象,实现懒加载逻辑。当访问如userList2.get(0).getOrderList()时,若满足条件,代理对象会调用懒加载查询方法获取数据。判断懒加载条件的关键在于结果集处理阶段,通过访问映射关系和查询映射值来确定是否执行后续懒加载查询。
综上所述,Mybatis的懒加载机制通过动态代理和结果集处理实现,旨在优化性能,按需加载数据,提高查询效率。通过核心配置和映射文件中的配置,懒加载逻辑被加载到项目中,为开发者提供灵活的加载策略。