app开发者平台在数字化时代的重要性与发展趋势解析
543
2023-08-01
Spring Bean常用的的装配方式详解
Bean常用的装配方式有3种:
基于xml的装配
基于Annotation(注解)的装配
基于java配置类的装配
基于xml的装配
在xml文件中配置Bean。
如果依赖很多,xml配置文件会很臃肿,后期维护、升级不方便。自动装配可解决这一问题。
基于xml的自动装配
在
autowire属性的属性值:
no 不使用自动装配。缺省autowire属性时默认值就是no。
byName 根据setter方法的名称来自动装配
byType 根据所依来的类型(Bean)来自动装配
constructor 根据构造函数的形参表的数据类型进行byType方式的自动装配
default 全局自动装配
1、byName
示例:
class Student{
private String name;
public Student(String name){
this.name=name;
}
public String getName(){
return name;
}
}
class Teacher{
private Student student;
public void setStudent(Student student) {
this.student = student;
}
public void say(){
System.out.println(student.getName()+",叫家长来一下。");
}
}
Teacher依赖于Student,依赖的对象要写成成员变量的形式。如果要使用自动装配,依赖对象的注入只能使用setter方式。
byName,name指的是setXxx()注入依赖的那个xxx,比如setStudent(Student student),name指的是student,将set后面的部分提出来,变成Camel写法。name不是指形参名的student。
xml中的配置:
第一个Bean是基于xml的普通装配,第二个Bean的配置是byName形式的自动装配。
byName自动装配的执行过程:在这个Bean的定义中,找到setter方法,这里是setStudent(),其name是student(set后面部分提出来,变成Camel写法),根据这个name(student)找打到id/name是student的Bean实例,将这个实例自动注入。
所以对
原本是要用
说明:自动装配只能完成setter形式的依赖注入,不能完成构造器方式的依赖注入,且只能注入其它Bean,不能注入String、数组、集合等Java自带的类型。
测试代码:
public class Test {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
Teacher teacher=applicationContext.getBean("teacher",Teacher.class);
teacher.say();
}
}
运行,控制台打印出"张三,叫家长来一下。"。
2、byType
根据要注入的Bean的类型来自动装配。
在上面的例子中,setStudent(Student student),要注入的依赖是Student类型的实例。
byType自动装配的执行过程:在这个Bean的定义中,找到setter方法,找到setter方法要注入的Bean的类型(Student),在Spring容器中找到Student类型的实例,注入。
如果Spring容器中该依赖有多个配置,比如:
它们都是Student这个Bean的配置,Spring容器不知道要注入的依赖是哪一个,会报错,所以依赖的bean只能有一个配置。
这种是可以的:
虽然Spring容器中可能有这个Bean的多个实例,但这些实例是一样的。
示例:
将byName示例中的xml中的配置修改如下即可
3、constructor
class Student{
public String getName(){
return "张三";
}
}
class Teacher{
private Student student;
public Teacher(Student student){
this.student=student;
}
public void say(){
System.out.println(student.getName()+",叫家长来一下。");
}
}
需要用构造器注入依赖,Spring容器会自动根据构造器中参数类型,用byType方式注入对应类型的依赖。
只能有一个构造器,否则Spring容器不知道使用哪个构造器。
xml中的配置:
4、default
xmlns:xsi="http://w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://springframework.org/schema/beans http://springframework.org/schema/beans/spring-beans.xsd" default-autowire="byName"> <bean id="student" class="my_package.Student"> 在 统一了应用的自动装配方式。 基于注解的装配 基于xml装配的方式,如果 基于注解的装配是最常用的。 Spring常用的注解: @Autowired 按类型自动装配(byType)。 HTSQZmNXF @Qualifier 按名称自动装配,不能单用,需要和@Autowired配合使用(byName)。 @Resource 是byName、byType方式的结合。 记法:Autowired——Type,Qualifier——Name,ATQN。 示例 @Autowired class Student{ private String name; public Student(String name){ this.name=name; } public String getName(){ return name; } } class Teacher{ @Autowired private Student student; public void say(){ System.out.println(student.getName()+",叫家长来一下。"); } } 不必写setter方法,也不必写构造器。在依赖的对象上添加@Autowired注解(当然也可以在setter方法上写),即按照类型自动装配依赖。 上面在Student类型的依赖上添加了@Autowired注解,会自动在Spring容器中,找到Student类型的Bean,注入。相当于byType。 xml中的配置: xmlns:xsi="http://w3.org/2001/XMLSchema-instance" xmlns:context="http://springframework.org/schema/context" xsi:schemaLocation="http://springframework.org/schema/beans http://springframework.org/schema/beans/spring-beans.xsd http://springframework.org/schema/context https://springframework.org/schema/context/spring-context.xsd"> 基于注解的装配都需要用 测试: public class Test { public static void main(String[] args) { ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml"); Teacher teacher=applicationContext.getBean("teacher",Teacher.class); teacher.say(); } } 可以看到控制台打印出"张三,叫家长来一下。"。 示例 @Qualifier 修改Teacher类代码如下,其余不变。 class Teacher{ @Autowired @Qualifier(value="student") private Student student; public void say(){ System.out.println(student.getName()+",叫家长来一下。"); } } 在依赖的Bean实例上添加@Qualifier,@Qualifier不能单独用,还需要添加@Autowired。 @Qualifier是byName方式的自动装配,需要用value指定依赖Bean的id/name,Spring容器根据这个value找到id/name为vBean,注入。 可简写为@Qualifier("student")。 示例 @Resource class Teacher{ @Resource(name = "student") private Student student; public void say(){ System.out.println(student.getName()+",叫家长来一下。"); } } 先根据name找到Spring容器中name/id为student的Bean,注入。即优先以getName方式。 如果找不到name/id为指定值的Bean,或缺省name直接写@Resource,则以默认的getName方式:写在字段上默认name为成员变量名(student),写在setter方法上默认为set后面部分得Camel写法,比如setStudent()默认name为student。 如果还是找不到依赖的Bean,则以byType方式注入。 说明 以上注解写在字段上、setter方法上均可,都是注入一个依赖。 Spring提供了@Resource注解,但此注解需要第三方包javax.annotation-api.jar的支持。如果用Maven,会自动添加Spring依赖的第三方包,比如commons-logging.jar、javax.annotation.jar,如果是自己添加Spring的jar库,则还需要手动添加Spring依赖的第三方jar包。 需要在xml中用 Spring常用的其它注解 @Service 将业务层(Service层)的类标识为Spring容器中的Bean @Controller 将控制层的类标识为Spring容器中的Bean @Repository 将数据访问层(Dao层)的类标识为Spring容器中的Bean @Component 将一个类标识为Spring容器中的Bean,相当于具有以上3个注解的功能。但一般都使用专门的,就是说通常使用上面3个注解,很少使用@Component。 前3个是专用的,第四个是通用的。这些注解都只能在类(Bean)上使用。 示例 @Service class Student{ public String getName(){ return "张三"; } } @Service class Teacher{ @Resource(name = "student") private Student student; public void say(){ System.out.println(student.getName()+",叫家长来一下。"); } } xml中的配置: 需要使用 其实上面4个注解的作用相当于 标注了这4个注解的类,Spring会自动在xml中把这个类配置为Bean,就是说在xml中不必写 但只能是 上面的例子中,Teacher类缺省了 @Resource(name = "student") private Student student; Teacher类要用到Student类的id/name,所以Student类写了配置。 其实不写Student类的配置,则会使用byType方式向Teacher注入依赖,也可以。 自动装配简化了配置,减少了代码量,但需要Spring容器做更多的工作,所以创建Bean的速度要慢一些。 基于Java配置类的装配 不使用xml文件配置Bean,而是单独写一个类来配置Bean。 class Student{ private String name; public Student(String name){ this.name=name; } public String getName(){ return name; } } class Teacher{ private Student student; public Teacher(Student student){ this.student=student; } public void say(){ System.out.println(student.getName()+",叫家长来一下。"); } } @Configuration //表示这个类是用来配置Bean的 class Config{ @Value("张三") String name; //创建一个成员变量,相当于String name="张三"; @Bean(name = "student") //配置一个Bean,相当于xml中的一个 public Student student(){ Student student=new Student(name); //创建并返回Bean的实例。 return student; } @Bean(name = "teacher") public Teacher teacher(){ return new Teacher(student()); //创建并返回Bean的实例,因为写了构造器,所以可以直接构造器注入依赖。可直接调用本类中的其它方法创建依赖的实例,注入。 } } public class Test { public static void main(String[] args) { ApplicationContext applicationContext=new AnnotationConfigApplicationContext(Config.class); //注意,和xml配置不同。参数是配置类。 Teacher teacher=applicationContext.getBean("teacher",Teacher.class); teacher.say(); } } 上面的例子是通过构造器初始化Bean,也可以写setter方法,通过setter方法初始化Bean: class Student{ private String name; public void setName(String name){ this.name=name; } public String getName(){ return name; } } class Teacher{ private Student student; public void setStudent(Student student){ this.student=student; } public void say(){ System.out.println(student.getName()+",叫家长来一下。"); } } @Configuration class Config{ @Value("张三") String name; @Bean(name = "student") public Student student(){ Student student=new Student(); student.setName(name); return student; } @Bean(name = "teacher") public Teacher teacher(){ Teacher teacher=new Teacher(); teacher.setStudent(student()); return teacher; } } 基于Java配置类的装配,会将Bean的配置耦合到应用代码中,不推荐使用。基于Java配置类的注解还有其它的,此处不再介绍。 使用xml文件配置Bean,是为了解耦,但随着Bean的增多,xml文件越来越臃肿,所以一般是折中使用注解+xml文件的方式。
xmlns:xsi="http://w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://springframework.org/schema/beans http://springframework.org/schema/beans/spring-beans.xsd"
default-autowire="byName">
<bean id="student" class="my_package.Student">
在
统一了应用的自动装配方式。
基于注解的装配
基于xml装配的方式,如果
基于注解的装配是最常用的。
Spring常用的注解:
@Autowired 按类型自动装配(byType)。
HTSQZmNXF @Qualifier 按名称自动装配,不能单用,需要和@Autowired配合使用(byName)。
@Resource 是byName、byType方式的结合。
记法:Autowired——Type,Qualifier——Name,ATQN。
示例 @Autowired
class Student{
private String name;
public Student(String name){
this.name=name;
}
public String getName(){
return name;
}
}
class Teacher{
@Autowired
private Student student;
public void say(){
System.out.println(student.getName()+",叫家长来一下。");
}
}
不必写setter方法,也不必写构造器。在依赖的对象上添加@Autowired注解(当然也可以在setter方法上写),即按照类型自动装配依赖。
上面在Student类型的依赖上添加了@Autowired注解,会自动在Spring容器中,找到Student类型的Bean,注入。相当于byType。
xml中的配置:
xmlns:xsi="http://w3.org/2001/XMLSchema-instance" xmlns:context="http://springframework.org/schema/context" xsi:schemaLocation="http://springframework.org/schema/beans http://springframework.org/schema/beans/spring-beans.xsd http://springframework.org/schema/context https://springframework.org/schema/context/spring-context.xsd">
xmlns:xsi="http://w3.org/2001/XMLSchema-instance" xmlns:context="http://springframework.org/schema/context" xsi:schemaLocation="http://springframework.org/schema/beans http://springframework.org/schema/beans/spring-beans.xsd http://springframework.org/schema/context https://springframework.org/schema/context/spring-context.xsd">
基于注解的装配都需要用
测试:
public class Test {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
Teacher teacher=applicationContext.getBean("teacher",Teacher.class);
teacher.say();
}
}
可以看到控制台打印出"张三,叫家长来一下。"。
示例 @Qualifier
修改Teacher类代码如下,其余不变。
class Teacher{
@Autowired
@Qualifier(value="student")
private Student student;
public void say(){
System.out.println(student.getName()+",叫家长来一下。");
}
}
在依赖的Bean实例上添加@Qualifier,@Qualifier不能单独用,还需要添加@Autowired。
@Qualifier是byName方式的自动装配,需要用value指定依赖Bean的id/name,Spring容器根据这个value找到id/name为vBean,注入。
可简写为@Qualifier("student")。
示例 @Resource
class Teacher{
@Resource(name = "student")
private Student student;
public void say(){
System.out.println(student.getName()+",叫家长来一下。");
}
}
先根据name找到Spring容器中name/id为student的Bean,注入。即优先以getName方式。
如果找不到name/id为指定值的Bean,或缺省name直接写@Resource,则以默认的getName方式:写在字段上默认name为成员变量名(student),写在setter方法上默认为set后面部分得Camel写法,比如setStudent()默认name为student。
如果还是找不到依赖的Bean,则以byType方式注入。
说明
以上注解写在字段上、setter方法上均可,都是注入一个依赖。
Spring提供了@Resource注解,但此注解需要第三方包javax.annotation-api.jar的支持。如果用Maven,会自动添加Spring依赖的第三方包,比如commons-logging.jar、javax.annotation.jar,如果是自己添加Spring的jar库,则还需要手动添加Spring依赖的第三方jar包。
需要在xml中用
Spring常用的其它注解
@Service 将业务层(Service层)的类标识为Spring容器中的Bean
@Controller 将控制层的类标识为Spring容器中的Bean
@Repository 将数据访问层(Dao层)的类标识为Spring容器中的Bean
@Component 将一个类标识为Spring容器中的Bean,相当于具有以上3个注解的功能。但一般都使用专门的,就是说通常使用上面3个注解,很少使用@Component。
前3个是专用的,第四个是通用的。这些注解都只能在类(Bean)上使用。
示例
@Service
class Student{
public String getName(){
return "张三";
}
}
@Service
class Teacher{
@Resource(name = "student")
private Student student;
public void say(){
System.out.println(student.getName()+",叫家长来一下。");
}
}
xml中的配置:
需要使用
其实上面4个注解的作用相当于
标注了这4个注解的类,Spring会自动在xml中把这个类配置为Bean,就是说在xml中不必写
但只能是
上面的例子中,Teacher类缺省了
@Resource(name = "student")
private Student student;
Teacher类要用到Student类的id/name,所以Student类写了配置。
其实不写Student类的配置,则会使用byType方式向Teacher注入依赖,也可以。
自动装配简化了配置,减少了代码量,但需要Spring容器做更多的工作,所以创建Bean的速度要慢一些。
基于Java配置类的装配
不使用xml文件配置Bean,而是单独写一个类来配置Bean。
class Student{
private String name;
public Student(String name){
this.name=name;
}
public String getName(){
return name;
}
}
class Teacher{
private Student student;
public Teacher(Student student){
this.student=student;
}
public void say(){
System.out.println(student.getName()+",叫家长来一下。");
}
}
@Configuration //表示这个类是用来配置Bean的
class Config{
@Value("张三") String name; //创建一个成员变量,相当于String name="张三";
@Bean(name = "student") //配置一个Bean,相当于xml中的一个
public Student student(){
Student student=new Student(name); //创建并返回Bean的实例。
return student;
}
@Bean(name = "teacher")
public Teacher teacher(){
return new Teacher(student()); //创建并返回Bean的实例,因为写了构造器,所以可以直接构造器注入依赖。可直接调用本类中的其它方法创建依赖的实例,注入。
}
}
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext=new AnnotationConfigApplicationContext(Config.class); //注意,和xml配置不同。参数是配置类。
Teacher teacher=applicationContext.getBean("teacher",Teacher.class);
teacher.say();
}
}
上面的例子是通过构造器初始化Bean,也可以写setter方法,通过setter方法初始化Bean:
class Student{
private String name;
public void setName(String name){
this.name=name;
}
public String getName(){
return name;
}
}
class Teacher{
private Student student;
public void setStudent(Student student){
this.student=student;
}
public void say(){
System.out.println(student.getName()+",叫家长来一下。");
}
}
@Configuration
class Config{
@Value("张三") String name;
@Bean(name = "student")
public Student student(){
Student student=new Student();
student.setName(name);
return student;
}
@Bean(name = "teacher")
public Teacher teacher(){
Teacher teacher=new Teacher();
teacher.setStudent(student());
return teacher;
}
}
基于Java配置类的装配,会将Bean的配置耦合到应用代码中,不推荐使用。基于Java配置类的注解还有其它的,此处不再介绍。
使用xml文件配置Bean,是为了解耦,但随着Bean的增多,xml文件越来越臃肿,所以一般是折中使用注解+xml文件的方式。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~