慣性聚合 高效追讀感興趣之博客、新聞、科技資訊
閱原文 以慣性聚合開啟

推薦訂閱源

博客园 - 司徒正美
V
V2EX
T
Tailwind CSS Blog
有赞技术团队
有赞技术团队
aimingoo的专栏
aimingoo的专栏
Apple Machine Learning Research
Apple Machine Learning Research
IT之家
IT之家
Blog — PlanetScale
Blog — PlanetScale
A
About on SuperTechFans
月光博客
月光博客
T
The Blog of Author Tim Ferriss
宝玉的分享
宝玉的分享
Martin Fowler
Martin Fowler
博客园 - 聂微东
The GitHub Blog
The GitHub Blog
V
Visual Studio Blog
WordPress大学
WordPress大学
酷 壳 – CoolShell
酷 壳 – CoolShell
Engineering at Meta
Engineering at Meta
GbyAI
GbyAI

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python)
Java 记录当有专属映射器
Dinuka Karun · 2026-05-24 · via DEV Community

自Java 16以降,Java Records已成定局;今Java 21已成长期支持版本,此物遍现——数据传输对象、值对象、领域模型皆是。其设计不可变,简练,且语义明晰。

然有隙焉,人皆不言:Java生态中诸般对象映射器,皆成于Records之先。者,乃循JavaBeans之制——可变之物,具取值、赋值之法,而无参构造之式。而Records则无此等物。然则何如?是故诸库皆以Records之部分支持为权宜之计,缝纫之迹昭然若揭。

吾乃建Immuto以补此缺憾。


后加Records之弊

一记录之身份,乃其正典构造也。

public record PersonDTO(Long id, String fullName, String email) {}

入全景模式 出全屏模式

彼构造函数者,是也造之途也PersonDTO无设值者。无构建者,非自为之则无。组件访问者唯读不可写。

既存之制图者,未尝为此而设。欲与记录相协,则或:

  • 生设法之呼而不存(遂于运行时败)
  • 需尔自撰可变之构器以权宜
  • 退而依隐私之域以映观——全然越乎正构之途

此皆运行时之败。非运行则不知其谬。


何以Immuto异于常者

Immuto乃注解处理器,其运行于mvn compile,若望Lombok与APT之法同工。其生平文也。.java调用汝记录之源文件正典构造函数直用无映像,无设置者,无运行时之意外。

@RecordMapper
public interface PersonMapper {

    @Mapping(target = "fullName",
             expression = "java(source.firstName() + \" \" + source.lastName())")
    PersonDTO toDto(PersonEntity source);

    @InheritInverseConfiguration(name = "toDto")
    PersonEntity toEntity(PersonDTO source);
}

入全景模式 退出全屏模式

mvn compile,Immuto乃书PersonMapperImpl.javatarget/generated-sources。其形貌,恰似亲笔所撰之码:

@Generated("io.github.karunarathnad.immuto.processor.RecordMapperProcessor")
public final class PersonMapperImpl implements PersonMapper, ImmutoMapper {

    @Override
    public PersonDTO toDto(PersonEntity source) {
        if (source == null) return null;
        return new PersonDTO(
            source.id(),
            source.firstName() + " " + source.lastName(),
            source.email()
        );
    }
}

进入全屏模式 退出全屏模式

此乃正宗之构,恒如是。此即Immuto所守之约也.


编译时之验

若记录组件不可映射,则构建失败—非运行时,非测试时,乃编译时也。

  • 未映射之组件 → 构建之误
  • 類型不協,無註冊轉換器 → 建構錯誤
  • @RecordMapper于类而非接口上构建 → 构建错误

此乃记录所宜之态。其设也,明且安;尔之映射器,亦当如是.


要点

嵌套记录 — 依构件名递归映射。用@Mapping(expression=...)以应非对称嵌套.

双向映射@InheritInverseConfiguration — 定toDto,得toEntity不取值。

@NullSafe— 以之裹其果Optional.ofNullable(...)于调用处:

@NullSafe
Optional<AddressDTO> toAddressDto(AddressEntity entity);

入全景模式 出全屏模式

封类支持- 亘互通晓封域之序,此乃今世诸图匠所不能也。

生命循环钩子-@BeforeMapping@AfterMapping之法,已内嵌于所生之码。无AOP,无代理。

定制之类型转换器

@Named("isoDate")
public class IsoDateConverter implements TypeConverter<LocalDate, String> {
    @Override
    public String convert(LocalDate source, MappingContext ctx) {
        return source == null ? null : source.toString();
    }
}

入全屏模式

流畅之运行时API:为测试或动态环境,APT不可用时:

FluentMapper<PersonEntity, PersonDTO> mapper = FluentMapper
    .from(PersonEntity.class)
    .to(PersonDTO.class)
    .override("fullName", p -> p.firstName() + " " + p.lastName())
    .build();

入全屏模式 :__JHSNS_SEG_674a7a43_70__

注:FluentMapper用反射——此乃显性选择之逃生通道,非默认路径也。


始之

<dependency>
    <groupId>io.github.karunarathnad</groupId>
    <artifactId>immuto-annotations</artifactId>
    <version>1.1.0</version>
</dependency>

<dependency>
    <groupId>io.github.karunarathnad</groupId>
    <artifactId>immuto-core</artifactId>
    <version>1.1.0</version>
</dependency>

<dependency>
    <groupId>io.github.karunarathnad</groupId>
    <artifactId>immuto-processor</artifactId>
    <version>1.1.0</version>
    <scope>provided</scope>
</dependency>

入全景模式 出全屏模式

于编译插件中添处理器路径

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <annotationProcessorPaths>
            <path>
                <groupId>io.github.karunarathnad</groupId>
                <artifactId>immuto-processor</artifactId>
                <version>1.1.0</version>
            </path>
        </annotationProcessorPaths>
    </configuration>
</plugin>

入全景模式 出全屏模式

注释之界面,运行之mvn compile,且用之。

PersonMapper mapper = Immuto.getMapper(PersonMapper.class);
PersonDTO dto = mapper.toDto(entity);

入全景模式 出全屏模式


何故于此?

Java 21乃今之长支持版本。记录非实验之物——乃现代Java中建模不可变数据之惯用之法。随更多代码库采用之,需治之工具亦随之增长,视之为首要公民(非边缘案例)。

Immuto 已登 Maven Central,依 Apache 2.0 许可,方在积极修整。

GitHub(IT之家)GitHub.com(karunarathnad/immuto)

惠赐评骘、陈弊、襄助,皆所欣然。