一、BeanUtils 的核心作用
BeanUtils?是 Apache Commons 和 Spring Framework 提供的工具類,主要用于簡化 JavaBean 的操作。核心功能包括:
- 屬性拷貝:對象間同名屬性自動復制
- 動態訪問:通過字符串名稱操作屬性
- 類型轉換:自動處理不同類型間的轉換
- 嵌套訪問:支持?
address.city
?格式的鏈式訪問
📌?JavaBean 定義:符合規范的 POJO 類
- 有無參構造函數
- 屬性私有化
- 提供 getter/setter 方法
二、Apache Commons BeanUtils
核心方法
方法 | 作用 | 示例 |
---|---|---|
copyProperties(dest, orig) | 復制同名屬性 | BeanUtils.copyProperties(userDTO, user); |
getProperty(bean, name) | 獲取屬性值 | String name = BeanUtils.getProperty(user, "name"); |
setProperty(bean, name, value) | 設置屬性值 | BeanUtils.setProperty(user, "age", "30"); |
describe(bean) | 對象轉 Map | Map<String, String> map = BeanUtils.describe(user); |
populate(bean, properties) | Map 轉對象 | BeanUtils.populate(user, map); |
?使用示例
// 添加依賴
// <dependency>
// <groupId>commons-beanutils</groupId>
// <artifactId>commons-beanutils</artifactId>
// <version>1.9.4</version>
// </dependency>import org.apache.commons.beanutils.BeanUtils;public class CommonsExample {public static void main(String[] args) throws Exception {// 1. 創建源對象User source = new User("Alice", 25, new Address("New York"));// 2. 創建目標對象UserDTO target = new UserDTO();// 3. 屬性拷貝(同名屬性自動復制)BeanUtils.copyProperties(target, source);System.out.println(target); // 輸出: UserDTO{name='Alice', age=25, city='New York'}// 4. 動態獲取屬性String city = BeanUtils.getProperty(source, "address.city");System.out.println(city); // 輸出: New York// 5. 動態設置屬性BeanUtils.setProperty(target, "age", "30"); // 字符串自動轉int// 6. 對象轉MapMap<String, String> map = BeanUtils.describe(source);System.out.println(map); // {name=Alice, age=25, address=Address[city=New York]}// 7. Map轉對象Map<String, Object> data = new HashMap<>();data.put("name", "Bob");data.put("age", "35"); // 字符串自動轉換data.put("address.city", "London"); // 嵌套屬性User newUser = new User();BeanUtils.populate(newUser, data);System.out.println(newUser.getAddress().getCity()); // 輸出: London}
}// JavaBean 類
class User {private String name;private int age;private Address address;// 無參構造器、getter/setter 省略
}class UserDTO {private String name;private int age;private String city; // 對應 address.city// 無參構造器、getter/setter 省略
}class Address {private String city;// 構造器、getter/setter 省略
}
?
?
三、Spring BeanUtils
核心方法(更簡潔高效)
方法 | 作用 | 特點 |
---|---|---|
copyProperties(source, target) | 屬性復制 | 無類型轉換,性能更好 |
copyProperties(source, target, ignoreProperties) | 帶忽略屬性的復制 | 跳過指定屬性 |
?
?使用示例
// 添加依賴
// <dependency>
// <groupId>org.springframework</groupId>
// <artifactId>spring-beans</artifactId>
// <version>5.3.20</version>
// </dependency>import org.springframework.beans.BeanUtils;public class SpringExample {public static void main(String[] args) {User source = new User("Alice", 25, new Address("New York"));UserDTO target = new UserDTO();// 1. 基礎屬性復制BeanUtils.copyProperties(source, target);System.out.println(target.getCity()); // 輸出: null (不自動處理嵌套)// 2. 帶忽略屬性的復制BeanUtils.copyProperties(source, target, "age"); // 忽略age屬性System.out.println(target.getAge()); // 輸出: 0 (默認值)// 3. 自定義屬性處理器class CustomConverter implements Converter {public Object convert(Class type, Object value) {if(value instanceof User) {return ((User) value).getAddress().getCity();}return null;}}// 4. 處理嵌套屬性(需自定義)String city = (String) new CustomConverter().convert(String.class, source);target.setCity(city);System.out.println(target.getCity()); // 輸出: New York}
}
?
四、最佳實踐與注意事項
1. 選擇指南
場景 | 推薦工具 |
---|---|
需要類型轉換 | Apache BeanUtils |
高性能場景 | Spring BeanUtils |
嵌套屬性訪問 | Apache BeanUtils |
簡單屬性復制 | Spring BeanUtils |
2. 性能對比
3. 常見問題解決
問題1:嵌套屬性復制失敗
// Apache 解決方案
BeanUtils.setProperty(target, "address.city", "Paris");// Spring 解決方案(需自定義)
class AddressMapper {public static void map(User source, UserDTO target) {target.setCity(source.getAddress().getCity());}
}
問題2:類型轉換錯誤
// 注冊自定義轉換器
ConvertUtils.register(new Converter() {public Object convert(Class type, Object value) {return LocalDate.parse(value.toString());}
}, LocalDate.class);// 現在可以處理字符串轉LocalDate
BeanUtils.setProperty(target, "birthDate", "2023-01-01");
問題3:忽略特定屬性
// Spring 方式
BeanUtils.copyProperties(source, target, "password", "sensitiveData");// Apache 方式(需額外處理)
Map<String, String> map = BeanUtils.describe(source);
map.remove("password");
BeanUtils.populate(target, map);
五、實際應用場景
場景1:DTO/VO 轉換
// Controller層
public UserDTO getUser(Long id) {User user = userService.findById(id);UserDTO dto = new UserDTO();BeanUtils.copyProperties(user, dto);return dto;
}
場景2:表單對象綁定
// 接收表單提交
public String createUser(@ModelAttribute UserForm form) {User user = new User();BeanUtils.copyProperties(form, user);userService.save(user);return "redirect:/users";
}
場景3:動態配置注入
// 從配置文件中讀取設置
@Value("${app.settings}")
private Map<String, String> settings;public void applySettings() {AppConfig config = new AppConfig();BeanUtils.populate(config, settings);
}
場景4:對象合并
public User mergeUserChanges(User original, User changes) {User merged = new User();BeanUtils.copyProperties(original, merged); // 復制原始數據BeanUtils.copyProperties(changes, merged); // 覆蓋變更數據return merged;
}
總結:BeanUtils 作用
- 消除樣板代碼:減少 getter/setter 調用
- 提升開發效率:簡化對象操作
- 增強靈活性:支持動態屬性訪問
- 降低耦合度:解耦對象操作邏輯