Spring’s BeanUtils bug? Maybe you’re using it wrong!

I have read an article “Before using Spring’s BeanUtils, it is recommended that you understand these pits”. It seems that there are still many public accounts Posting this recently. Today, I would like to talk about my opinion based on actual operation.

In this article, the author finally draws the following conclusions:

    1. Spring’s BeanUtils CopyProperties method requires getters and setters for deserved properties;
    1. If there are inner classes with identical properties, but not the same inner class, that is, separate inner classes, Spring will assume that the properties are different and will not Copy.
    1. Generics only work at compile time. You can’t rely on generics for runtime restrictions.
    1. Finally, Spring and Apache get the copy property with the method source and destination arguments in opposite positions, so you need to pay attention to the following when importing packages and calling them.

Here, we focus on today is the second point, the first point is because use reflection to get set and get methods to get attribute values and set attribute values, people who do not understand reflection can baidu below. The third and fourth points are simple enough that they need no explanation.

validation

First, I’ll post my own test code:

@Data
public class TestEntity{
    private Integer age;
    private String name;
    private Inner inner;
    
    @Data
    public static class Inner{
        private Integer a;
        public Inner(Integer a){
            this.a = a; }}}Copy the code
@Data
public class TestVO{
    private Integer age;
    private String name;
    private Inner inner;
    

    @Data
    public static class Inner{
        private Integer a;
        public Inner(Integer a){
            this.a = a; }}}Copy the code

public class Main{
    public static void main(String args[]){
        TestEntity entity = new TestEntity();
        entity.setAge(1);
        entity.setName("hehe");
        entity.setInner(new TestEntity.Inner(1));

        TestVO vo = newTestVO(); BeanUtils.copyProperties(entity,vo); System.out.println(vo.toString()); }}Copy the code

The above are the three classes I have, isn’t it super simple? For example, when entity is converted to VO in work, there is such a use scenario, and the main method is run. The test results are as follows

B: Inner is null!

But why? Is this a BUG? And that’s what I want to focus on today.

We know that Java gives us Inner classes, but Java Inner classes are just syntax candy. So what does Inner look like in our two Java classes?

When we go to the compiled.class file directory, we can see the compiled.class file:

Ha ha, I wonder if the reader can understand something here? Beanutils.copyproperties (Entity,vo) inner null Testentity. Java and testvo. Java have different Inner class names (representing different addresses after loading into virtual machine).

So the question is, how do we copy it successfully? I modified my code slightly as follows:

@Data
public class TestVO{
    private Integer age;
    private String name;
    private TestEntity.Inner inner;
}
Copy the code

Just change Inner to testEntity. Inner, delete the Inner class without reference, main.java unchanged, and run as follows:

As you can see, the inner from the b object has been copied successfully.

At this point, the compiled class files are also changed from 5 to 4

conclusion

In fact, Spring’s beanutils.copyproperties does not have this kind of flaw, but we do not grasp the essence of our own mistakes. I believe that those who can read this kind of article want to understand Spring or improve their development ability. When we read a thing, we should clearly understand its essence, at least its working principle, especially the things we use for development. Otherwise, how can we face a very complicated software?