Java确保LocalCacheData不被修改

分类:软件编程
阅读:1658
作者: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

    @Data
    public class UserProfile {
        private String no;
        private String nickname;
        private List<String> hobbies;
    }
    
  • CacheUtils

    public static class CacheUtils {
    
    //----初始化数据----
            private static UserProfile userProfile;
    
            static {
                UserProfile profile = new UserProfile();
                profile.setNo("1");
                profile.setNickname("zs");
                profile.setHobbies(Lists.newArrayList("Java","Go"));
                // 包装成不可变对象
                userProfile = (UserProfile) ImmutableBean.create(profile);
            }
    //----初始化数据----
    
            public static UserProfile getUserProfile(){
                return userProfile;
            }
     }
    
  • Junit Test

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

总结:

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

集合对象

  • CacheUtils

    public  static class CacheUtils {
    
    //----初始化数据----  
            static Map<String, UserProfile> userProfileMap;
    
            static {
                Map<String,UserProfile> map = new HashMap<>(3);
                for (int i = 0; i < 3; i++) {
                    UserProfile profile = new UserProfile();
                    profile.setNo(""+(i+1));
                    profile.setNickname("nn_"+(i+1));
    
                    // 包装成不可变对象
                    UserProfile userProfile = (UserProfile) ImmutableBean.create(profile);
    
                    map.put(userProfile.getNo(),userProfile);
                }
    
                userProfileMap = Collections.unmodifiableMap(map);
            }
    //----初始化数据----
    
            public static Map<String, UserProfile> getUserProfiles(){
                return userProfileMap;
            }
    }
    
  • Junit Test

    @Test
    public void collection(){
      Map<String, UserProfile> userProfiles = CacheUtils.getUserProfiles();
      userProfiles.forEach((k,v)->{
        System.out.println(k+" , "+v);
      });
    
    
      /*
      userProfiles.remove("1");
      */
      //上述方法执行会报错 java.lang.UnsupportedOperationException,  at java.util.Collections$UnmodifiableMap.remove(Collections.java:1460)
    
    
      /*
      UserProfile profile = new UserProfile();
      profile.setNo("444");
      profile.setNickname("nn_444");
      userProfiles.put("444",profile);
      */
      //上述方法执行会报错 java.lang.UnsupportedOperationException , at java.util.Collections$UnmodifiableMap.put(Collections.java:1457)
    
    
      /*
      UserProfile profile = userProfiles.get("1");
      profile.setNickname("marion");
      */
      //上述方法执行会报错 java.lang.IllegalStateException: Bean is immutable
    }
    

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

    profile.setHobbies(Collections.unmodifiableList(Lists.newArrayList("Java","Go")));
    

总结

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

image-20220109190354832