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://www.cnblogs.com/chenpi/p/6222595.html,如需转载请自行联系原作者

相关文章
|
5月前
|
XML Java 测试技术
Spring IOC—基于注解配置和管理Bean 万字详解(通俗易懂)
Spring 第三节 IOC——基于注解配置和管理Bean 万字详解!
361 26
|
4月前
|
JSON 前端开发 Java
Spring MVC常用的注解
@RequestMapping:用于处理请求 url 映射的注解,可用于类或方法上。用于类上,则表示类中 的所有响应请求的方法都是以该地址作为父路径。 @RequestBody:注解实现接收http请求的json数据,将json转换为java对象。 @ResponseBody:注解实现将conreoller方法返回对象转化为json对象响应给客户。 @Controller:控制器的注解,表示是表现层,不能用用别的注解代替 @RestController : 组合注解 @Conntroller + @ResponseBody @GetMapping , @PostMapping , @Put
|
4月前
|
Java Spring
Spring Boot的核心注解是哪个?他由哪几个注解组成的?
Spring Boot的核心注解是@SpringBootApplication , 他由几个注解组成 : ● @SpringBootConfiguration: 组合了- @Configuration注解,实现配置文件的功能; ● @EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项 ● @ComponentScan:Spring组件扫描
|
4月前
|
Java 测试技术 Spring
SpringBoot+@Async注解一起用,速度提升
本文介绍了异步调用在高并发Web应用性能优化中的重要性,对比了同步与异步调用的区别。同步调用按顺序执行,每一步需等待上一步完成;而异步调用无需等待,可提升效率。通过Spring Boot示例,使用@Async注解实现异步任务,并借助Future对象处理异步回调,有效减少程序运行时间。
121 3
|
3月前
|
人工智能 缓存 自然语言处理
保姆级Spring AI 注解式开发教程,你肯定想不到还能这么玩!
这是一份详尽的 Spring AI 注解式开发教程,涵盖从环境配置到高级功能的全流程。Spring AI 是 Spring 框架中的一个模块,支持 NLP、CV 等 AI 任务。通过注解(如自定义 `@AiPrompt`)与 AOP 切面技术,简化了 AI 服务集成,实现业务逻辑与 AI 基础设施解耦。教程包含创建项目、配置文件、流式响应处理、缓存优化及多任务并行执行等内容,助你快速构建高效、可维护的 AI 应用。
|
5月前
|
监控 Java Spring
SpringBoot:SpringBoot通过注解监测Controller接口
本文详细介绍了如何通过Spring Boot注解监测Controller接口,包括自定义注解、AOP切面的创建和使用以及具体的示例代码。通过这种方式,可以方便地在Controller方法执行前后添加日志记录、性能监控和异常处理逻辑,而无需修改方法本身的代码。这种方法不仅提高了代码的可维护性,还增强了系统的监控能力。希望本文能帮助您更好地理解和应用Spring Boot中的注解监测技术。
136 16
|
4月前
|
XML Java 数据库连接
微服务——SpringBoot使用归纳——Spring Boot集成MyBatis——基于注解的整合
本文介绍了Spring Boot集成MyBatis的两种方式:基于XML和注解的形式。重点讲解了注解方式,包括@Select、@Insert、@Update、@Delete等常用注解的使用方法,以及多参数时@Param注解的应用。同时,针对字段映射不一致的问题,提供了@Results和@ResultMap的解决方案。文章还提到实际项目中常结合XML与注解的优点,灵活使用两者以提高开发效率,并附带课程源码供下载学习。
100 0
|
分布式计算 Java 大数据
[Spring实战系列](9)装配集合
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/SunnyYoona/article/details/50634498 前两篇文章中,我们已经了解了如何使用Spring 配置简单属性值(使用value 属性)和引用其他Bean 的属性(使用ref 属性)。
1059 0
|
4月前
|
前端开发 Java 数据库
微服务——SpringBoot使用归纳——Spring Boot集成Thymeleaf模板引擎——Thymeleaf 介绍
本课介绍Spring Boot集成Thymeleaf模板引擎。Thymeleaf是一款现代服务器端Java模板引擎,支持Web和独立环境,可实现自然模板开发,便于团队协作。与传统JSP不同,Thymeleaf模板可以直接在浏览器中打开,方便前端人员查看静态原型。通过在HTML标签中添加扩展属性(如`th:text`),Thymeleaf能够在服务运行时动态替换内容,展示数据库中的数据,同时兼容静态页面展示,为开发带来灵活性和便利性。
121 0
|
4月前
|
XML Java 数据库连接
微服务——SpringBoot使用归纳——Spring Boot集成MyBatis——基于 xml 的整合
本教程介绍了基于XML的MyBatis整合方式。首先在`application.yml`中配置XML路径,如`classpath:mapper/*.xml`,然后创建`UserMapper.xml`文件定义SQL映射,包括`resultMap`和查询语句。通过设置`namespace`关联Mapper接口,实现如`getUserByName`的方法。Controller层调用Service完成测试,访问`/getUserByName/{name}`即可返回用户信息。为简化Mapper扫描,推荐在Spring Boot启动类用`@MapperScan`注解指定包路径避免逐个添加`@Mapper`
127 0

热门文章

最新文章