zoukankan      html  css  js  c++  java
  • Spring bean依赖注入、bean的装配及相关注解

    依赖注入

    Spring主要提供以下两种方法用于依赖注入

    • 基于属性Setter方法注入
    • 基于构造方法注入

    Setter方法注入

    例子:

    public class Communication {
     
        private Messaging messaging;
          
         /*
         * DI via Setter
         */
        public void setMessaging(Messaging messaging){
            this.messaging = messaging;
        }
     
        public void communicate(){
            messaging.sendMessage();
        }
    }

    如上Communication类有一个messaging属性,并含有setMessaging方法,那么使用Setter方法注入的时候,只需要使用如下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-4.0.xsd
                                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
     
        <bean id="activeMqMessaging" class="com.websystique.spring.domain.impl.ActiveMQMessaging" />
     
        <bean id="communication" class="com.websystique.spring.Communication">
            <property name="messaging">
                <ref bean="activeMqMessaging" />
            </property>
        </bean>
     
    </beans>

    这里省略了ActiveMQMessaging的定义,实际上ActiveMQMessaging类是Messaging接口的一个实现类。

    构造方法注入

    例子

    public class Communication {
     
        private Encryption encryption;
         
        /*
         * DI via Constructor Injection
         */
        public Communication(Encryption encryption){
            this.encryption = encryption;
        }
     
     
        public void communicate(){
            encryption.encryptData();
        }
     
    }

    注意以上Communication类有一个构造方法Communication(Encryption encryption),且含有一个入参,类型为Encryption,那么使用构造方法注入的时候,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-4.0.xsd
                                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
     
        <bean id="rsaEncryption" class="com.websystique.spring.domain.impl.RSAEncryption" />
     
        <bean id="communication" class="com.websystique.spring.Communication">
            <constructor-arg type="com.websystique.spring.domain.Encryption">
                <ref bean="rsaEncryption" />
            </constructor-arg>
        </bean>
     
    </beans>

    注意,这里省略了RSAEncryption的定义,不用在意这些细节,该类是Encryption接口的一个实现类。

    另外,为了避免构造方法重载带来的歧义,这里指定了入参类型为com.websystique.spring.domain.Encryption。

    装配

    bean的装配有两种方式,手动装配和自动装配。注意,不要混淆,bean的装配是依赖注入的具体行为,依赖注入的时候需要根据bean的名称或类型等进行装配。

    手动装配:通过在<property> 或者 <constructor>标签中使用ref属性,在上一小节的“依赖注入”部分使用的就是手动装配;

    <!-- default example (autowire="no") -->
    <bean id="driver" class="com.websystique.spring.domain.Driver">
        <property name="license" ref="license"/>
    </bean>
     
    <bean id="license" class="com.websystique.spring.domain.License" >
        <property name="number" value="123456ABCD"/>
    </bean>

    自动装配:在<bean>标签中使用autowire属性;

    <bean id="application" class="com.websystique.spring.domain.Application" autowire="byName"/>

    本小节主要关注自动装配,自动装配有以下四种方式:

    • autowire="byName" : 根据名称
    • autowire="byType" : 根据类型
    • autowire="constructor" : 根据构造方法入参类型
    • autowire="no" : 不使用自动装配,即默认方式,手动装配

    autowire="byName"

    例子:

    public class Application {
     
        private ApplicationUser applicationUser;
     
        public ApplicationUser getApplicationUser() {
            return applicationUser;
        }
     
        public void setApplicationUser(ApplicationUser applicationUser) {
            this.applicationUser = applicationUser;
        }
     
        @Override
        public String toString() {
            return "Application [applicationUser=" + applicationUser + "]";
        }
    }

    该类有一个属性叫applicationUser,那么根据名称自动装配的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-4.0.xsd
                                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
     
        <!-- byName example -->
        <bean id="application" class="com.websystique.spring.domain.Application" autowire="byName"/>
     
        <bean id="applicationUser" class="com.websystique.spring.domain.ApplicationUser" >
            <property name="name" value="superUser"/>
        </bean>
    </beans>

    autowire="byType"

    例子

    public class Employee {
     
        private EmployeeAddress address;
     
        public EmployeeAddress getAddress() {
            return address;
        }
     
        public void setAddress(EmployeeAddress address) {
            this.address = address;
        }
     
        @Override
        public String toString() {
            return "Employee [address=" + address + "]";
        }
    }

    该类有一个属性类型为EmployeeAddress,那么根据类型自动装配的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-4.0.xsd
                                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
     
        <!-- byType example -->
        <bean id="employee" class="com.websystique.spring.domain.Employee" autowire="byType"/>
     
        <bean id="employeeAddress" class="com.websystique.spring.domain.EmployeeAddress" >
            <property name="street" value="112/223,SantaVila"/>
            <property name="city" value="Nebraska"/>
        </bean>
     
    </beans>

    autowire="constructor"

    例子

    public class Performer {
         
        private Instrument instrument;
         
        public Performer(Instrument instrument){
            this.instrument = instrument;
        }
     
        @Override
        public String toString() {
            return "Performer [instrument=" + instrument + "]";
        }
    }

    该类有一个构造方法,入参的类型为Instrument,那么根据构造方法自动装配的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-4.0.xsd
                                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
     
        <!-- constructor example -->
        <bean id="performer" class="com.websystique.spring.domain.Performer" autowire="constructor"/>
     
        <bean id="instrument" class="com.websystique.spring.domain.Instrument" >
            <property name="name" value="PIANO"/>
        </bean>
     
    </beans>

    autowire="no"

    public class Driver {
     
        private License license;
         
        public void setLicense(License license) {
            this.license = license;
        }
     
        public License getLicense() {
            return license;
        }
     
        @Override
        public String toString() {
            return "Driver [license=" + license + "]";
        }
    }

    该类有一个属性license,由于我们不打算使用自动装配功能,那么只能使用手动装配了,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-4.0.xsd
                                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
     
        <!-- default example (autowire="no") -->
        <bean id="driver" class="com.websystique.spring.domain.Driver" autowire="no">
            <property name="license" ref="license"/>
        </bean>
     
        <bean id="license" class="com.websystique.spring.domain.License" >
            <property name="number" value="123456ABCD"/>
        </bean>
     
    </beans>

    注意,如果不配置license的ref引用的话,license将为null。

    相关注解

    主要涉及以下三个注解

    • @Autowired
    • @Resource
    • @Qualifier

    @Autowired可应用于构造方法、属性、setter方法或配置类@Configuration的方法上,该注解根据bean的数据类型进行装配,如果你想希望根据bean的名称进行装配可以使用带name属性的@Resource注解;另外@Qualifier注解经常与@Autowired注解结合使用,用于解决一个应用中存在多个同种类型的bean的情况,下面将给出各个注解的示例。

    @Autowired(根据类型自动装配)

    setter方法上

    @Component("driver")
    public class Driver {
     
        private License license;
         
        @Autowired
        public void setLicense(License license) {
            this.license = license;
        }
     
        @Override
        public String toString() {
            return "Driver [license=" + license + "]";
        }
        //getter
    }

    构造方法上

    @Component("driver")
    public class Driver {
     
        private License license;
         
        @Autowired
        public Driver(License license){
            this.license = license;
        }
         
        @Override
        public String toString() {
            return "Driver [license=" + license + "]";
        }
    }

    属性上

    @Component("driver")
    public class Driver {
        @Autowired
        private License license;
         
        //getter,setter
     
        @Override
        public String toString() {
            return "Driver [license=" + license + "]";
        }
    }

    @Resource(根据名称装配)

    @Component("application")
    public class Application {
     
        @Resource(name="applicationUser")
        private ApplicationUser user;
     
        @Override
        public String toString() {
            return "Application [user=" + user + "]";
        }
    }

    @Qualifier(与@Autowired结合使用,实现按名称装配)

    例子背景::存在两个Car接口的实现类,其中一个Car接口的实现类已被注册为bean,且name为Mustang

    @Component
    public class Bond {
     
        @Autowired
        @Qualifier("Mustang")
        private Car car;
         
        public void showCar(){
            car.getCarName();
        }
    }

    注意,以上例子如果不使用@Qualifier限定的话,将抛出如下异常,表明存在多个类型相同的bean:

    Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.websystique.spring.domain.Car] is defined: expected single matching bean but found 2: Ferari,Mustang
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:970)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:858)
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:480)
        ... 14 more

    最后提醒下,被@Autowired注解标注默认情况下能保证成功注入,如果注入不成功(往往是找不到,或存在歧义),Spring会抛出异常。当然,有时候可能会有特殊需求,不希望bean被强制装配,那么可以在@Autowired上添加required=false属性,表明该bean的装配是可选的,找不到的话,就为null吧,如下示例:

    @Component("driver")
    public class Driver {
        @Autowired(required=false)
        private License license;
         
        //getter,setter
     
        @Override
        public String toString() {
            return "Driver [license=" + license + "]";
        }
    }

    基于以上原因,虽然@Autowired注解与@Resource功能类似,但是@Autowired还是比@Resource强大了那么一点点,个人建议使用@Autowired注解。

    参考资料

    http://websystique.com/spring/spring-dependency-injection-example-with-constructor-and-property-setter-xml-example/

    http://websystique.com/spring/spring-beans-auto-wiring-example-using-xml-configuration/

    http://websystique.com/spring/spring-dependency-injection-annotation-beans-auto-wiring-using-autowired-qualifier-resource-annotations-configuration/

     
  • 相关阅读:
    iot 表索引dump《2》
    heap表和iot表排序规则不同
    Cannot complete the install because one or more required items could not be found.
    iot表输出按主键列排序,heap表不是
    iot 表主键存放所有数据,且按数据插入顺序排序
    iot表和heap表排序规则不同
    org.eclipse.graphiti.ui.editor.DiagramEditorInput.
    Oracle 排序规则
    perl 异步超时 打印错误
    14.6.3 Grouping DML Operations with Transactions 组DML操作
  • 原文地址:https://www.cnblogs.com/chenpi/p/6222595.html
Copyright © 2011-2022 走看看