Java确保LocalCacheData不被修改

分类:软件编程
阅读:6098
作者:majingjing
发布:2022-01-09 19:06

在Java开发的时候,经常会使用LocalCache来加快方法的执行时间,

但是在对外暴露方法的时候, LocalCacheData 被调用开发者莫名的Modify , 导致程序出现问题.

下面介绍下如何设计确保LocalCacheData不被修改

有如下两种方式结合使用

  • ImmutableBean

    保证单个bean对象不被修改

    包名 org.springframework.cglib.beans.ImmutableBean

  • Collections.unmodifiableXXX

    保证集合对象不被修改

    包名 java.util.Collections

单个bean对象

  • LocalCache Class

    1. @Data
    2. public class UserProfile {
    3. private String no;
    4. private String nickname;
    5. private List<String> hobbies;
    6. }
  • CacheUtils

    1. public static class CacheUtils {
    2. //----初始化数据----
    3. private static UserProfile userProfile;
    4. static {
    5. UserProfile profile = new UserProfile();
    6. profile.setNo("1");
    7. profile.setNickname("zs");
    8. profile.setHobbies(Lists.newArrayList("Java","Go"));
    9. // 包装成不可变对象
    10. userProfile = (UserProfile) ImmutableBean.create(profile);
    11. }
    12. //----初始化数据----
    13. public static UserProfile getUserProfile(){
    14. return userProfile;
    15. }
    16. }
  • Junit Test

    1. @Test
    2. public void object(){
    3. UserProfile userProfile = CacheUtils.getUserProfile();
    4. System.out.println(userProfile);
    5. /*
    6. userProfile.setNickname("marion");
    7. System.out.println(userProfile);
    8. */
    9. //上述方法执行会报错 java.lang.IllegalStateException: Bean is immutable
    10. /*
    11. userProfile.getHobbies().add("Python");
    12. System.out.println(userProfile);
    13. */
    14. //上述方法执行会成功 UserProfile(no=1, nickname=zs, hobbies=[Java, Go, Python])
    15. //解决办法参考下文 "集合对象"
    16. }

总结:

  • 保证单个bean对象不被外部程序修改
  • 不保证集合对象的修改操作

集合对象

  • CacheUtils

    1. public static class CacheUtils {
    2. //----初始化数据----
    3. static Map<String, UserProfile> userProfileMap;
    4. static {
    5. Map<String,UserProfile> map = new HashMap<>(3);
    6. for (int i = 0; i < 3; i++) {
    7. UserProfile profile = new UserProfile();
    8. profile.setNo(""+(i+1));
    9. profile.setNickname("nn_"+(i+1));
    10. // 包装成不可变对象
    11. UserProfile userProfile = (UserProfile) ImmutableBean.create(profile);
    12. map.put(userProfile.getNo(),userProfile);
    13. }
    14. userProfileMap = Collections.unmodifiableMap(map);
    15. }
    16. //----初始化数据----
    17. public static Map<String, UserProfile> getUserProfiles(){
    18. return userProfileMap;
    19. }
    20. }
  • Junit Test

    ```java
    @Test
    public void collection(){
    Map<String, UserProfile> userProfiles = CacheUtils.getUserProfiles();
    userProfiles.forEach((k,v)->{

    1. System.out.println(k+" , "+v);

    });

  1. /*
  2. userProfiles.remove("1");
  3. */
  4. //上述方法执行会报错 java.lang.UnsupportedOperationException, at java.util.Collections$UnmodifiableMap.remove(Collections.java:1460)
  5. /*
  6. UserProfile profile = new UserProfile();
  7. profile.setNo("444");
  8. profile.setNickname("nn_444");
  9. userProfiles.put("444",profile);
  10. */
  11. //上述方法执行会报错 java.lang.UnsupportedOperationException , at java.util.Collections$UnmodifiableMap.put(Collections.java:1457)
  12. /*
  13. UserProfile profile = userProfiles.get("1");
  14. profile.setNickname("marion");
  15. */
  16. //上述方法执行会报错 java.lang.IllegalStateException: Bean is immutable

}

  1. > 要保证 **UserProfile.hobbies** 不被修改,需要在初始化缓存的时候设置
  2. >
  3. >

profile.setHobbies(Collections.unmodifiableList(Lists.newArrayList(“Java”,”Go”)));
```

总结

  • 如果我们设计的 cache 数据有集合和对象, 可以将 上述两种方式结合使用

image-20220109190354832