依赖注入和依赖查找的类型

一、依赖注入的类型

1.构造函数注入

        (1)应用场景

                在使用组件之前,必须有一个依赖类的实例,并且该依赖是不可变的,不为null。这时候推荐选择构造函数注入,相反,没有依赖实例就无法创建组件。

        (2)实现方式

                ①xml:

public class MessageProvider{

    private String message;
    public MessageProvider(String message){
        this.message = message;
    }

}
<bean id="messageProvider" class=".....">
<constructor-arg value="hahahah" />
</bean>

如果包含多个参数,通常要在<constructor-arg> 标签上使用index标记 。从 0开始。

                ②注解:

@Service
public class MessageProvider{

    private String message;
    @Autowired
    public MessageProvider(@Value("hello") String message){
        this.message = message;
    }

}

可以用@Value注解,并且支持Spel表达式。还可以创建message的bean来进行注入。对于多参数可以使用@Qualifier()注解标记在每个参数前面(是参数前面,不是方法前面)

③构造注入的好处:

这个构造器注入的方式,能够保证注入的组件不可变,并且确保需要的依赖不为空。此外,构造器注入的依赖总是能够在返回客户端(组件)代码的时候保证完全初始化的状态

  • 依赖不可变:其实说的就是final关键字。
  • 依赖不为空(省去了我们对其检查):当要实例化FooController的时候,由于自己实现了有参数的构造函数,所以不会调用默认构造函数,那么就需要Spring容器传入所需要的参数,所以就两种情况:1、有该类型的参数->传入,OK 。2:无该类型的参数->报错。所以保证不会为空,Spring总不至于传一个null进去吧 。
  • 完全初始化的状态:这个可以跟上面的依赖不为空结合起来,向构造器传参之前,要确保注入的内容不为空,那么肯定要调用依赖组件的构造方法完成实例化。而在Java类加载实例化的过程中,构造方法是最后一步(之前如果有父类先初始化父类,然后自己的成员变量,最后才是构造方法,这里不详细展开)。所以返回来的都是初始化之后的状态。

2.setter注入

        (1)应用场景 大多数应用场景都可适用,尤其是依赖可选的环境。

        (2)实现方式

                ①xml:

@Service
public class MessageProvider{

    private String message;
 
    public void setMessage(String message)
    {
        this.message=message;
     }

}
<bean id="messageProvider" class=".....">
  <property name="message" value="hahahah" />
</bean>

                ②注解:

@Service
public class MessageProvider{

    private String message;
 
    @Autowired
    public void setMessage(String message)
    {
        this.message=message;
     }

}

 使用@Resource()效果相同

                ③setter注入的好处:后期可以改变相关依赖,对于多依赖情况相比构造函数注入更加简洁。最好设置默认值,否则需要判空。

3.字段注入

        (1)实现方式

               ①注解:

@Service
public class Demo{

    @Autowired
    private MessageProvider messageProvider;
}

(2)字段注入存在的问题

①依赖无法对外部暴露。

②与容器耦合度强,在new 对象时,如果调用其依赖的方法会报空指针异常。

③容易造成一个类额依赖过多,违反单一责任原则

④不能精确的确定想要的依赖类型(如果字段为接口,那么其实现类都能注入进来)

4.查找方法注入

        (1)应用场景 当两个bean的生命周期不相同时,使用方法查找,但效率低

        (2)实现方式

                ①注解

@Component
@Scope(value="prototype")
public class Singer{
    
    private String singInfo="i am a singer";

    
    public void sing()
    {
        System.out.println(singInfo);
    }

}

          

public class Demo{

@Lookup("singer")
public Singer getSinger()
{
    return null;
}
} 

   注意,使用@lookup注解标记的参数,需要返回参数为null

   ②xml


public class Singer{
    
    private String singInfo="i am a singer";

    
    public void sing()
    {
        System.out.println(singInfo);
    }

}
<bean id="" >
    <lookup-method name="getMysinger" bean="singer" />
</bean>

         

public abstract class Demo{


public abstract Singer getMySinger();

} 

需要注意该方法是抽象的 bean是返回的bean的id,name是方法名

5.方法替换

        (1)应用场景 一些不可修改的类,但想按照自己的逻辑运行时

        (2)实现方式

package com.lhf.replacement;

public class TestServiceImpl {

    public void say() {
        System.out.println("我说你是猪1");
    }

    public void say(String mes) {
        System.out.println("我说你是猪2");
    }

    public void say(Object mes) {
        System.out.println("我说你是猪3");
    }
}
ackage com.lhf.replacement;

import org.springframework.beans.factory.support.MethodReplacer;

import java.lang.reflect.Method;

public class Replace implements MethodReplacer {

    @Override
    public Object reimplement(Object obj, Method method, Object[] args) throws Throwable {
        System.out.println("替换原来的方法");
        return null;
    }
}

<?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:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="replace" class="com.lhf.replacement.Replace"/>

    <bean id="testService" class="com.lhf.replacement.TestServiceImpl">
        <replaced-method name="say" replacer="replace">
            <arg-type/>
        </replaced-method>
        <replaced-method name="say" replacer="replace">
            <arg-type match="java.lang.String"/>
        </replaced-method>
        <replaced-method name="say" replacer="replace">
            <arg-type match="java.lang.Object"/>
        </replaced-method>
    </bean>
</beans>

二、依赖查找的类型

1.依赖拉取

        (1) 应用场景:几乎不用

        (2)实现方式

 

2.上下文依赖查找

        (1)应用场景:几乎不用

        (2)实现方式  :通过实现类似接口

 

三、注入方式的选择 

field代码简洁,尽管面临许多问题但还是程序员最常用的注入方式,使用强依赖时使用构造注入,可选依赖时使用setter注入。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值