<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    CTO:禁止在項目中使用 BeanUtils 屬性轉換工具。。。

    VSole2023-01-09 10:49:28

    1 背

    之前講過“不推薦使用屬性拷貝工具”,薦直接定義轉換類和方法使用 IDEA 插件自動填充 get / set 函數。

    不推薦的主要理由是:

    有些屬性拷貝工具性能有點差 有些屬性拷貝工具有“BUG” 使用屬性拷貝工具容易存在一些隱患(后面例子會講到)

    2 示例

    首先公司內部就遇到過 commons 包的 BeanUtils 進行屬性拷貝性能較差的真實案例,然后該同事換成了 Spring 的 BeanUtils 性能好了很多,感興趣大家可以使用性能測試框架或者基準測試框架去對比,這里就不對比了。

    接下來我們看 Spring 的 BeanUtils 的屬性拷貝會存在啥問題:

    import lombok.Data;
    import java.util.List;
    @Data
    public class A {
        private String name;
        private List ids;
    }
    @Data
    public class B {
        private String name;
        private List ids;
    }
    import org.springframework.beans.BeanUtils;
    import java.util.Arrays;
    public class BeanUtilDemo {
        public static void main(String[] args) {
            A first = new A();
            first.setName("demo");
            first.setIds(Arrays.asList(1, 2, 3));
            B second = new B();
            BeanUtils.copyProperties(first, second);
            for (String each : second.getIds()) {// 類型轉換異常
                System.out.println(each);
            }
        }
    }
    

    大家運行上述示例時,會發生類型轉換異常。

    打斷點可以看到,屬性拷貝之后 B 類型的 second 對象中 ids 仍然為 Integer 類型:

    如果不轉換為字符串,直接進行打印,并不會報錯。

    使用CGlib 在不定義Converter 的情況下也會遇到類似問題:

    import org.easymock.cglib.beans.BeanCopier;
    import java.util.Arrays;
    public class BeanUtilDemo {
        public static void main(String[] args) {
            A first = new A();
            first.setName("demo");
            first.setIds(Arrays.asList(1, 2, 3));
            B second = new B();
            final BeanCopier beanCopier = BeanCopier.create(A.class, B.class, false);
            beanCopier.copy(first,second,null);
            for (String each : second.getIds()) {// 類型轉換異常
                System.out.println(each);
            }
        }
    }
    

    同樣,問題在運行時才暴露出來。

    接下來我們看下 mapstruct:

    import org.mapstruct.Mapper;
    import org.mapstruct.factory.Mappers;
    @Mapper
    public interface Converter {
        Converter INSTANCE = Mappers.getMapper(Converter.class);
        B aToB(A car);
    }
    import java.util.Arrays;
    public class BeanUtilDemo {
        public static void main(String[] args) {
            A first = new A();
            first.setName("demo");
            first.setIds(Arrays.asList(1, 2, 3));
            B second = Converter.INSTANCE.aToB(first);
            for (String each : second.getIds()) {// 正常
                System.out.println(each);
            }
        }
    }
    

    可以成功的將 A 中 List 轉為 B 中的 List 類型。

    我們看下編譯生成的 Converter 實現類:

    import java.util.ArrayList;
    import java.util.List;
    import javax.annotation.Generated;
    import org.springframework.stereotype.Component;
    @Generated(
        value = "org.mapstruct.ap.MappingProcessor",
        comments = "version: 1.3.1.Final, compiler: javac, environment: Java 1.8.0_202 (Oracle Corporation)"
    )
    @Component
    public class ConverterImpl implements Converter {
        @Override
        public B aToB(A car) {
            if ( car == null ) {
                return null;
            }
            B b = new B();
            b.setName( car.getName() );
            b.setIds( integerListToStringList( car.getIds() ) );
            return b;
        }
        protected List integerListToStringList(List list) {
            if ( list == null ) {
                return null;
            }
            List list1 = new ArrayList( list.size() );
            for ( Integer integer : list ) {
                list1.add( String.valueOf( integer ) );
            }
            return list1;
        }
    }
    

    自動幫我們進行了轉換,我們可能沒有意識到類型并不一致。

    如果我們在 A 類中添加一個 String number 屬性,在 B 類中添加一個 Long number 屬性,使用 mapstruect 當 number 設置為非數字類型時就會報 .NumberFormatException

    @Override
    public B aToB(A car) {
        if ( car == null ) {
            return null;
        }
        B b = new B();
        b.setName( car.getName() );
        if ( car.getNumber() != null ) { // 問題出在這里
            b.setNumber( Long.parseLong( car.getNumber() ) );
        }
        b.setIds( integerListToStringList( car.getIds() ) );
        return b;
    }
    

    使用 cglib 默認則不會映射 number 屬性,B 中的 number 為 null。

    如果手動定義轉換器,使用 IDEA 插件(如 generateO2O)自動轉換:

    public final class A2BConverter {
        public static B from(A first) {
            B b = new B();
            b.setName(first.getName());
            b.setIds(first.getIds());
            return b;
        }
    }
    

    在編碼階段就可以非常明確地發現這個問題:

    3 結論

    由于 Java 的泛型其實是編譯期檢查,編譯后泛型擦除,導致運行時 List List 都是 List 類型,可以正常賦值。這就導致在使用很多屬性映射工具時,編譯時不容易明顯的錯誤。

    mapstruct 自定義了注解處理器,在編譯階段可以讀取映射雙方的泛型類型,進而進行映射。但是這種映射也很可怕,有時候我們由于粗心等原因定義錯了類型,自動幫助我們進行了轉換,會帶了很多副作用。

    之前對各種屬性映射工具的性能進行了簡單的對比,結果如下:

    因此慎用屬性轉換工具,如果可能建議自定義轉換類,使用IDEA插件自動填充,效率也挺高, A 或 B 中任何屬性類型不匹配,甚至刪除一個屬性,編譯階段即可報錯,而且直接調用 get set 的效率也是非常高的。

    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    1 背之前講過“不推薦使用屬性拷貝工具”,薦直接定義轉換類和方法使用 IDEA 插件自動填充 get / set 函數。接下來我們看 Spring 的 BeanUtils屬性拷貝會存在啥問題:import?大家運行上述示例時,會發生類型轉換異常。打斷點可以看到,屬性拷貝之后 B 類型的 second 對象 ids 仍然為 Integer 類型:如果不轉換為字符串,直接進行打印,并不會報錯。使用CGlib 不定義Converter 的情況下也會遇到類似問題:import?可以成功的將 A List 轉為 B 的 List 類型。
    RSAConference2022將于舊金山時間6月6日召開。大會的Innovation Sandbox(沙盒)大賽作為“安全圈的奧斯卡”,每年都備受矚目,成為全球網絡安全行業技術創新和投資的風向標。 前不久,RSA官方宣布了最終入選創新沙盒的十強初創公司:Araali Networks、BastionZero、Cado Security、Cycode、Dasera、Lightspin、Neos
    RSAConference2022將于舊金山時間6月6日召開。大會的Innovation Sandbox(沙盒)大賽作為“安全圈的奧斯卡”,每年都備受矚目,成為全球網絡安全行業技術創新和投資的風向標。 前不久,RSA官方宣布了最終入選創新沙盒的十強初創公司:Araali Networks、BastionZero、Cado Security、Cycode、Dasera、Lightspin、Neos
    其備受追捧的同時,ChatGPT也面臨數據安全方面的爭議。ChatGPT訓練數據的安全性問題引起各方高度關注。律師王藝表示,如何對AI技術應用進行有效監管以切實防范相關風險是世界各國重點關注的問題,AI技術應用的監管已從理論探討走向立法、執法實踐階段。對于更多潛在問題,需要時刻關注新法新規對生成式AI的規制。吳沈括表示,目前數據權屬界定不明的歷史過渡階段,數據抓取、數據融合匯聚的合規問題必然更加突出。
    目前該公司已正式更名為Colombo Technology,公司主要提供安全審計、滲透測試和網絡安全咨詢等服務。
    1、中國網絡安全產品與廠商大全 物理安全 存儲介質信息消除/粉碎機:北信源、和升達、科密、30所、利譜、交大捷普、蘭天致信、超偉業、博智安全、方德信安、深圳匯...
    百川(網路游俠)更新時間:2020年8月21日游俠安全網: 1、中國網絡安全產品與廠商大全 物理安全 存儲介質信息消除/粉碎機:北信源、和升達、科密、30所、利譜、交大捷普、蘭天致信、超偉業、博智安全、方德信安、...
    本文主要介紹MAC地址相關的7配置示例。
    Evil Corp 網絡犯罪團伙正在使用一種名為 Macaw Locker 的新型勒索軟件來逃避美國的制裁,該制裁阻止受害者支付贖金。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类