美文网首页
Spring Bean 的装配方式以及Autowired与Res

Spring Bean 的装配方式以及Autowired与Res

作者: 冬天里的懒喵 | 来源:发表于2021-08-31 19:06 被阅读0次

    1.Spring的自动装配

    在Spring的使用中,如果要将一个bean实例化,可以通过配置文件,也可以通过在java代码里面的注解来实现,Spring能够根据自动协作这些bean之间的关系,这种自动协作的过程,也称之为自动装配。
    自动装配模式有如下四种模式:

    模式 说明
    no no表示关闭自动装配选项,必须通过显示的设置才能确认依赖关系。这也是采用xml配置的默认选项。
    byname 基于bean的名称name进行注入,在进行Bean的自动装配时,将属性的name在配置文件中搜索匹配的Bean,如果找到name一致的bean,则进行注入,如果找不打到,则会抛出异常。
    byType 基于bean的类型进行注入,在bean中自动装配属性的时候,将定义的属性类型与配置文件中定义的bean进行匹配,如果类型一致,就在属性中注入,如果没有找到这样的bean,就抛出异常。
    constructor 通过构造函数自动装配bean,这个操作与ByType是一致的,在自动装配的过程中,将查找构造函数的参数类型,然后对所有构造函数参数执行自动装配。

    有三种方式可以实现spring Bean的装配过程:

    • xml配置
    • @Autowired
    • @Resource

    2.xml配置实现装配

    首先定义了三个类, 分别为:

    表示用户关系的User类 :

    package com.dhb.gts.javacourse.week5.springbean.v1;
    
    import lombok.Data;
    
    @Data
    public class User {
        //编号
        private int id;
        //姓名
        private String name;
        //年龄
        private int age;
    
        public User(int id, String name, int age) {
            this.id = id;
            this.name = name;
            this.age = age;
        }
    }
    
    

    表示角色的Role类:

    package com.dhb.gts.javacourse.week5.springbean.v1;
    
    import lombok.Data;
    
    @Data
    public class Role {
        //角色ID
        private int roleId;
        //角色名称
        private String roleName;
    }
    
    

    以及表示用户角色关联关系的UserRole类:

    package com.dhb.gts.javacourse.week5.springbean.v1;
    
    import lombok.Data;
    
    @Data
    public class UserRole {
        //用户
        private User user;
        //角色
        private Role role;
    
        public UserRole() {
        }
    
        public UserRole(User user, Role role) {
            this.user = user;
            this.role = role;
        }
    }
    
    

    2.1 xml实现基本的装配

    配置xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="user" class="com.dhb.gts.javacourse.week5.springbean.v1.User">
            <constructor-arg name="id" value="001"/>
            <constructor-arg name="name" value="张三"/>
            <constructor-arg name="age" value="22"/>
        </bean>
        
        <bean id="role" class="com.dhb.gts.javacourse.week5.springbean.v1.Role">
            <property name="roleId" value="1"/>
            <property name="roleName" value="管理员"/>
        </bean>
        
        <bean id="userRole" class="com.dhb.gts.javacourse.week5.springbean.v1.UserRole" >
            <property name="role" ref="role"/>
            <property name="user" ref="user"/>
        </bean>
        
    </beans>
    

    测试类:

    package com.dhb.gts.javacourse.week5.springbean.v1;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class XmlTest1 {
    
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("app-v1-1.xml");
            UserRole userRole = (UserRole) context.getBean("userRole");
            System.out.println(userRole.toString());
        }
    
    }
    
    
    

    这种方式需要在xml中对每一个属性进行配置,首先通过property装配了User和Role,UserRole对象的两个属性role和user通过property进行关联。这样就能实现spring中最基本的一种装配方式。
    可以通过XmlTest1类进行测试,确认装配的正确性。

    UserRole(user=User(id=1, name=张三, age=22), role=Role(roleId=1, roleName=管理员))
    

    2.2 xml通过byName实现自动装配

    xml配置代码:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="user" class="com.dhb.gts.javacourse.week5.springbean.v1.User">
            <constructor-arg name="id" value="001"/>
            <constructor-arg name="name" value="张三"/>
            <constructor-arg name="age" value="22"/>
        </bean>
        
        <bean id="role" class="com.dhb.gts.javacourse.week5.springbean.v1.Role">
            <property name="roleId" value="1"/>
            <property name="roleName" value="管理员"/>
        </bean>
    
        <bean id="userRole" class="com.dhb.gts.javacourse.week5.springbean.v1.UserRole" autowire="byName"/>
        
    </beans>
    

    测试代码:

    package com.dhb.gts.javacourse.week5.springbean.v1;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class XmlTest2 {
    
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("app-v1-2.xml");
            UserRole userRole = (UserRole) context.getBean("userRole");
            System.out.println(userRole.toString());
        }
    
    }
    
    
    

    这种装配方式不用在UserRole中指定user和role对应的具体类,只需要增加一个属性:autowire="byName",就能在自动装配的过程中,将根据UserRole的属性的name查找context中name与之对应的bean进行装配。
    测试结果如下:

    UserRole(user=User(id=1, name=张三, age=22), role=Role(roleId=1, roleName=管理员))
    

    2.3 xml通过byType实现自动装配

    xml配置代码:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="user" class="com.dhb.gts.javacourse.week5.springbean.v1.User">
            <constructor-arg name="id" value="001"/>
            <constructor-arg name="name" value="张三"/>
            <constructor-arg name="age" value="22"/>
        </bean>
        
        <bean id="role" class="com.dhb.gts.javacourse.week5.springbean.v1.Role">
            <property name="roleId" value="1"/>
            <property name="roleName" value="管理员"/>
        </bean>
    
        <bean id="userRole" class="com.dhb.gts.javacourse.week5.springbean.v1.UserRole" autowire="byType"/>
        
    </beans>
    

    测试代码:

    package com.dhb.gts.javacourse.week5.springbean.v1;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class XmlTest3 {
    
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("app-v1-3.xml");
            UserRole userRole = (UserRole) context.getBean("userRole");
            System.out.println(userRole.toString());
        }
    
    }
    
    
    

    这种装配方式同样不用在UserRole中指定user和role对应的具体类,只需要增加一个属性:autowire="byType",就能在自动装配的过程中,将根据UserRole成员变量的类型查找context中类型与之对应的bean进行装配。
    需要注意的是,byName方式可以确保bean的唯一性,但是byType方式,无法确保bean的唯一性,如果出现多个bean的类型相同,则会报错。
    测试结果如下:

    UserRole(user=User(id=1, name=张三, age=22), role=Role(roleId=1, roleName=管理员))
    

    2.4 xml通过constructor实现自动装配

    xml配置代码:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="user" class="com.dhb.gts.javacourse.week5.springbean.v1.User">
            <constructor-arg name="id" value="001"/>
            <constructor-arg name="name" value="张三"/>
            <constructor-arg name="age" value="22"/>
        </bean>
        
        <bean id="role" class="com.dhb.gts.javacourse.week5.springbean.v1.Role">
            <property name="roleId" value="1"/>
            <property name="roleName" value="管理员"/>
        </bean>
    
        <bean id="userRole" class="com.dhb.gts.javacourse.week5.springbean.v1.UserRole" autowire="constructor">
            <constructor-arg name="user" ref="user"/>
            <constructor-arg name="role" ref="role"/>
        </bean>
    </beans>
    

    测试代码:

    package com.dhb.gts.javacourse.week5.springbean.v1;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class XmlTest4 {
    
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("app-v1-4.xml");
            UserRole userRole = (UserRole) context.getBean("userRole");
            System.out.println(userRole.toString());
        }
    
    }
    
    
    

    这种装配方式同样不用在UserRole中指定user和role对应的具体类,只需要增加一个属性:autowire="constructor",就能在自动装配的过程中,将根据UserRole构造函数参数表constructor-arg配置的name查找context中name与之对应的bean进行装配。
    测试结果如下:

    UserRole(user=User(id=1, name=张三, age=22), role=Role(roleId=1, roleName=管理员))
    

    2.@Autowired实现装配

    @Autowired是采用byType实现的自动装配,在装配的过程中,通过类型进行匹配。
    同样,定义了Role

    package com.dhb.gts.javacourse.week5.springbean.v2;
    
    import lombok.Data;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    
    @Component
    @Data
    public class Role {
        //角色ID
        @Value("2")
        private Integer roleId;
        //角色名称
        @Value("用户")
        private String roleName;
    }
    
    

    以及User

    package com.dhb.gts.javacourse.week5.springbean.v2;
    
    import lombok.Data;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    
    @Component
    @Data
    public class User {
        //编号
        private Integer id;
        //姓名
        private String name;
        //年龄
        private Integer age;
    
        @Autowired
        public User(@Value("1") int id, @Value("用户") String name,@Value("22")  int age) {
            this.id = id;
            this.name = name;
            this.age = age;
        }
    }
    
    

    2.1 注解在属性上

    UserRole代码如下:

    package com.dhb.gts.javacourse.week5.springbean.v2;
    
    import lombok.Data;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    @Component
    @Data
    public class UserRole {
        //用户
        @Autowired
        private User user;
        //角色
        @Autowired
        private Role role;
    
        public UserRole() {
        }
    
        public UserRole(User user, Role role) {
            this.user = user;
            this.role = role;
        }
    }   
    
    

    如上所示,只需要在UserRole的属性上增加@Autpwired,在context中查找与属性类型一致的bean,就可以实现UserRole的自动装配。

    2.2 注解在构造函数上

    UserRole代码如下:

    package com.dhb.gts.javacourse.week5.springbean.v2;
    
    import lombok.Data;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    @Component
    @Data
    public class UserRole1 {
        //用户
        private User user;
        //角色
        private Role role;
    
        public UserRole1() {
        }
    
        @Autowired
        public UserRole1(User user, Role role) {
            this.user = user;
            this.role = role;
        }
    }
    
    

    注解在构造函数上,等价于xml配置中的constructor配置。通过构造函数的属性值的类型去查找context中的bean。

    2.3 注解在Set方法上

    UserRole代码如下:

    package com.dhb.gts.javacourse.week5.springbean.v2;
    
    import lombok.ToString;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    @Component
    @ToString
    public class UserRole2 {
       //用户
       private User user;
       //角色
       private Role role;
    
    
       public User getUser() {
           return user;
       }
    
       @Autowired
       public void setUser(User user) {
           this.user = user;
       }
    
       public Role getRole() {
           return role;
       }
    
       @Autowired
       public void setRole(Role role) {
           this.role = role;
       }
    
       public UserRole2() {
       }
       
       public UserRole2(User user, Role role) {
           this.user = user;
           this.role = role;
       }
    }
    
    

    AutoWired也可以注解在set方法上来实现自动装配。根据set方法的参数,从context中选择type与之一致的bean实现装配。

    2.4 测试

    测试代码如下:

    public class AutowiredTest {
    
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("app-v2.xml");
            UserRole userRole = (UserRole) context.getBean("userRole");
            System.out.println(userRole.toString());
            UserRole1 userRole1 = (UserRole1) context.getBean("userRole1");
            System.out.println(userRole1.toString());
            UserRole2 userRole2 = (UserRole2) context.getBean("userRole2");
            System.out.println(userRole2.toString());
        }
    }
    

    xml配置:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    
        <context:component-scan base-package="com.dhb.gts.javacourse.week5.springbean.v2">
            <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        </context:component-scan>
        
    </beans>
    

    测试结果:

    UserRole(user=User(id=1, name=用户, age=22), role=Role(roleId=2, roleName=用户))
    UserRole1(user=User(id=1, name=用户, age=22), role=Role(roleId=2, roleName=用户))
    UserRole2(user=User(id=1, name=用户, age=22), role=Role(roleId=2, roleName=用户))
    

    3.@Resource实现装配

    同样,通过J2EE的@Resource标签也能实现Bean的装配,但是需要注意的是,这个注解不支持构造函数,只支持属性或者set方法。需要注意的是,@Resource默认是采用byName的方式从contect中查找bean.
    角色类:

    package com.dhb.gts.javacourse.week5.springbean.v3;
    
    import lombok.Data;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    
    @Component
    @Data
    public class Role {
        //角色ID
        @Value("2")
        private Integer roleId;
        //角色名称
        @Value("用户")
        private String roleName;
    }
    
    

    用户类:

    package com.dhb.gts.javacourse.week5.springbean.v3;
    
    import lombok.Data;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    
    @Component
    @Data
    public class User {
        //编号
        private Integer id;
        //姓名
        private String name;
        //年龄
        private Integer age;
    
        @Autowired
        public User(@Value("1") int id, @Value("用户") String name,@Value("22")  int age) {
            this.id = id;
            this.name = name;
            this.age = age;
        }
    }
    
    

    3.1 注解在属性上

    代码如下:

    package com.dhb.gts.javacourse.week5.springbean.v3;
    
    import lombok.Data;
    import org.springframework.stereotype.Component;
    
    import javax.annotation.Resource;
    
    @Component
    @Data
    public class UserRole {
        //用户
        @Resource(type = User.class)
        private User user;
        //角色
        @Resource(name = "role")
        private Role role;
    
        public UserRole() {
        }
    
        public UserRole(User user, Role role) {
            this.user = user;
            this.role = role;
        }
    }
    
    

    3.2 注解在set方法上

    代码如下:

    package com.dhb.gts.javacourse.week5.springbean.v3;
    
    import lombok.ToString;
    import org.springframework.stereotype.Component;
    
    import javax.annotation.Resource;
    
    @Component
    @ToString
    public class UserRole1 {
        //用户
        private User user;
        //角色
        private Role role;
    
        public UserRole1() {
        }
    
        public User getUser() {
            return user;
        }
    
        @Resource
        public void setUser(User user) {
            this.user = user;
        }
    
        public Role getRole() {
            return role;
        }
    
        @Resource
        public void setRole(Role role) {
            this.role = role;
        }
        
        public UserRole1(User user, Role role) {
            this.user = user;
            this.role = role;
        }
    }
    
    

    3.3 @Resource测试:

    测试类:

    public class ResourceTest {
    
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("app-v3.xml");
            UserRole userRole = (UserRole) context.getBean("userRole");
            System.out.println(userRole.toString());
            UserRole1 userRole1 = (UserRole1) context.getBean("userRole1");
            System.out.println(userRole1.toString());
        }
    }
    
    

    测试配置:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    
        <context:component-scan base-package="com.dhb.gts.javacourse.week5.springbean.v3">
            <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        </context:component-scan>
        
    </beans>
    
    

    测试结果:

    UserRole(user=User(id=1, name=用户, age=22), role=Role(roleId=2, roleName=用户))
    UserRole1(user=User(id=1, name=用户, age=22), role=Role(roleId=2, roleName=用户))
    

    4.@Autowired与@Resource的比较

    二者对比如下:

    • @Autowired与@Resource都可以用来装配bean. 都可以写在字段上,或者在setter方法上。 但是@Resource不支持在构造函数上装配。
    • @Autowired默认按类型装配(这个注解是属业spring的),默认情况下必须要求依赖对象必须存在,如果要允许null 值,可以设置它的required属性为false,如:@Autowired(required=false) 。如果我们想使用名称装配可以结合@Qualifier注解进行使用。
    • @Resource(这个注解属于J2EE的),默认安照名称进行装配,名称可以通过name属性进行指定, 如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找,如果注解写在setter方法上默认取属性名进行装配。 当找不到与名称匹配的bean时才按照类型进行装配。

    相关文章

      网友评论

          本文标题:Spring Bean 的装配方式以及Autowired与Res

          本文链接:https://www.haomeiwen.com/subject/wpoziltx.html