关于lombok常用注解使用的案例。
区别:
@NoArgsConstructor
:生成无参的构造方法。
@AllArgsConstructor
:生成该类下全部属性的构造方法。
@RequiredArgsConstructor
:生成该类下被 final 修饰或者 non-null 字段生成一个构造方法。
@Data
:为所有字段生成 getter、toString 方法,non-transient 字段的 hashCode 和 equals 方法,非 non-final 字段的 setter 方法和无参构造方法。@Data
等价于 @Getter
@Setter
@RequiredArgsConstructor
@ToString
@EqualsAndHashCode
注解合集。
@UtilityClass
:标记当前类为 final 修饰,私有无参构造方法,所有方法、内部类、所有字段都标记为 static,不允许有参构造方法。
场景:
在springboot中,对于一个bean类,注入其他bean的时候,常见的是使用@Autowired,实际上也可以使用构造函数注入,这个时候就可以使用@AllArgsConstructor或者@RequiredArgsConstructor来代替。
@NoArgsConstructor 默认都知道。若不知道怎么查看java反编译字节码内容,可以看一下: Java 如何进行反编译生成.java文件(javap、jad下载安装使用)
- @AllArgsConstructor
@AllArgsConstructor
public class AllArgsConstructorDemo {
private String name;
// 被final修饰
private final int age;
@NonNull
private String sex;
}
根据反编译查看代码:
import org.springframework.lang.NonNull;
public class AllArgsConstructorDemo {
private String name;
private final int age;
@NonNull
private String sex;
// 默认 只要是该类下的字段,无论什么修饰,都会被参与构造
public AllArgsConstructorDemo(String name, int age, @NonNull String sex) {
if (sex == null) {
throw new NullPointerException("sex is marked non-null but is null");
} else {
this.name = name;
this.age = age;
this.sex = sex;
}
}
}
这是源码的英文解释:
- @RequiredArgsConstructor
@RequiredArgsConstructor
public class RequiredArgsConstructorDemo {
private String name;
// 被final修饰
private final int age;
@NonNull
private String sex;
}
反编译代码:
import org.springframework.lang.NonNull;
public class RequiredArgsConstructorDemo {
private String name;
private final int age;
@NonNull
private String sex;
// 只构造了有final或者no-null修饰的字段
public RequiredArgsConstructorDemo(int age, @NonNull String sex) {
if (sex == null) {
throw new NullPointerException("sex is marked non-null but is null");
} else {
this.age = age;
this.sex = sex;
}
}
}
这是源码的英文解释:
- @Data
@Data
public class DataDemo {
private String name;
private int age;
private String sex;
}
反编译代码:
public class DataDemo {
private String name;
private int age;
private String sex;
public DataDemo() {}
public String getName() {}
public int getAge() {}
public String getSex() {}
public void setName(String name) {}
public void setAge(int age) {}
public void setSex(String sex) {}
public boolean equals(Object o) {}
protected boolean canEqual(Object other) {}
public int hashCode() {}
public String toString() {}
}
这是源码的英文解释:
- @UtilityClass
@UtilityClass
public class UtilityDemo {
private String name;
private int age;
private String sex;
}
反编译代码:
public final class UtilityDemo {
private static String name;
private static int age;
private static String sex;
private UtilityDemo() {
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
}
}
这是源码的英文解释:
- @AllArgsConstructor
根据上面看反编译代码可以得出:只要是类里面字段,都会被加入到构造函数里面,不管被什么修饰。
例子:
@Component
public class BeanOne {}
@Component
public class BeanTwo {}
@Component
public class BeanThree {}
@Component
@AllArgsConstructor
@ToString
public class BeansDemo {
// 注入三个bean对象,完全没有使用Autowired注解
private BeanOne beanOne;
@NonNull
private BeanTwo beanTwo;
private final BeanThree beanThree;
}
// 这只是个测试类
@Component
public class BeansRunner implements ApplicationRunner {
@Autowired
BeansDemo beansDemo;
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println(beansDemo);
}
}
完完全全可以注入bean对象。
- @RequiredArgsConstructor
RequiredArgsConstructor:只会构造被final修饰或者no-null修饰的字段。
@Component
@RequiredArgsConstructor
@ToString
public class BeansDemo {
private BeanOne beanOne;
@NonNull
private BeanTwo beanTwo;
private final BeanThree beanThree;
}
由图可以看出,没有被修饰final或者no-null的属性无法被注入,因此,建议使用@RequiredArgsConstructor的时候,对需要的字段加上final修饰。注:强调 对需要的字段,为什么要强调,请看下面的例子:
- @RequiredArgsConstructor 与 @AllArgsConstructor 在注入bean上的区别
根据上面两个例子,我们可以看出无论是那种方法都可以注入bean属性对象,只是@RequiredArgsConstructor 是针对有条件的,没有什么区别。
但如果是下面的需求呢:
在该类下,部分字段还需要使用@Value来注入值呢?
@Component
@AllArgsConstructor
@ToString
public class BeansDemo {
private BeanOne beanOne;
@NonNull
private BeanTwo beanTwo;
private final BeanThree beanThree;
@Value("${hello.name:world}")
private String name;
}
// 先思考一下:
// 一个bean如果使用构造函数进行bean属性注入,那么当然构造函数不能加上name。
// 因为加上,在创建ConstructorDemo该bean的时候,需要找类型为String,名字是name的bean对象,当然是不存在,必然会报错。
// 因此,当然不能使用@AllArgsConstructor了,只能使用@RequiredArgsConstructor
@AllArgsConstructor例子:
@Component
@AllArgsConstructor
@ToString
public class BeansDemo {
private BeanOne beanOne;
@NonNull
private BeanTwo beanTwo;
private final BeanThree beanThree;
// Parameter 3 of constructor in org.olinonee.framework.lombok.bean.BeansDemo required a bean of type 'java.lang.String' that could not be found.
@Value("${hello.name:world}")
private String name;
}
@RequiredArgsConstructor的例子
@Component
@RequiredArgsConstructor
@ToString
public class BeansDemo {
private BeanOne beanOne;
@NonNull
private BeanTwo beanTwo;
private final BeanThree beanThree;
@Value("${hello.name:world}")
private String name;
}
上面只是举例了代替@Autowired
的例子,实际上在json转化为对象,以及在spring中从配置文件读取配置使用@ConfigurationProperties
以及@ConstructorBinding
的时候,都可以使用构造函数赋值,都可以用到上面的两个@AllArgsConstructor
、@RequiredArgsConstructor
。
具体:只要记得,哪些字段需要赋值,就把它列进构造方法的参数里面即可。
@NoArgsConstructor、@AllArgsConstructor、@RequiredArgsConstructor的区别以及在springboot常用地方
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。