Ioc容器,我们最常使用的就是依赖注入方式了,也是为了解耦,刚开始其实觉得这个解耦主要是解开了创建对象这个步骤,减少了代码的重复性,将各个模块可以相对没有适用spring之前那样减少相互的依赖,相对便利,后面经过使用次数的增多以及阅览相关资料的篇幅逐渐增加,开始慢慢理解IOC模型的好处,它并不是启动的时候就将配置文件或者注解等元信息和JavaBean的类信息加载到IOC容器并根据配置创建模型,而是根据是否调用,再来像机械装配一样,以配置好的形式创建并注入(或者说创建)到需要并且属于扫描区域(或setter方法中)的应用类中。不常用的依赖查找就不在这里提及了。

 

鉴于之前已经提及了spring的依赖注入,那么直接上例子。

源码传送门,1.4部分,讲解注入

目录

一、延迟加载

二、单例多例

三、依赖注入

1、通过构造方法进行依赖注入

xml(普通字符串)

普通javaBean

用于注入的javaBean

注入xml(注入javaBean)

测试类

2.通过setter的方法进行依赖注入(推荐)

xml(普通字符串)

javaBean

注入JavaBean

xml注入javaBean

测试方法

3、基于命名空间

p-namespace (property)

c-namespace (constructor-arg)

四、@Lookup注入

方式一

方式二


一、延迟加载


默认情况下,不是延迟加载,加载完配置后,已经创建完对象

如果配置了延迟加载,单例用到的时候才创建,且只创建一次

 default : 默认值 false,不是延迟加载

  false: 不是延迟加载

  true: 代表延迟加载,使用到这个类的时候再去创建对象

 

<bean id="g4" class="com.linge.d_DI_setter.Gender" lazy-init="true">
<propecomponentrty name="gender" value="男"></property>
</bean>

 

二、单例多例


默认为单例模式,如果为多例,则设置延迟加载为false失效,即必须延迟加载

<bean id="g4" class="com.linge.d_DI_setter.Gender" scope="prototype">
<property name="gender" value="男"></property>
</bean>

 

 * 1、singleton:单例(默认情况下是单例 )

 *  2、prototype:多例

 *  3、request:一个请求一个实例

 *  4、session:一个回话一个实例

 

一般只有在Action也就是视图层才会用到多例

 

 

三、依赖注入


 

下文所用的xml文档,统一使用 applicationContext_DI.xml 放置于src目录下,不再提及。

 

<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-3.0.xsd">

 

web.xml

<listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
     <param-name>contextConfigLocation</param-name>
     <param-value>classpath:config/applicationContext_*.xml</param-value>//配置文件所在位置
    </context-param>

 

 

 

 

 


构造方法注入--无参构造


1、通过构造方法进行依赖注入

xml(普通字符串)

<bean id="s1" class="com.linge.c_DI.Student">
<constructor-arg name="namesss" value="小泽"/>
</bean>

 

 

普通javaBean

public class Student {
//注入的普通的参数String+8大类型
private String name;
//无参的构造方法最好放回来
public Student(){
}
//通过我们有参构造方法进行依赖注入
public Student(String namesss){
this.name = namesss;
}
public String toString() {
return "Student [name=" + namesss};
}

 


构造方法注入---注入javaBean


用于注入的javaBean

public class Score {
private Integer score;
//通过有参的构造方法注入分数
public Score(Integer score) {
super();
this.score = score;
} 
 
public Score() {
super();
}
@Override
public String toString() {
return "Score [score=" + score + "]";
}

 

注入xml(注入javaBean)

<bean id="score1" class="com.linge.c_DI.Score">
<constructor-arg name="score" value="100"></constructor-arg>
</bean>
<bean id="s2" class="com.linge.c_DI.Student">
<constructor-arg name="name" value="小麻"></constructor-arg>
<!-- ref: 指的是bean的id,引用的JavaBean的id -->
<constructor-arg name="score" ref="score1"></constructor-arg>
</bean>

 

 

测试类

public void test1(){
ApplicationContext context  =
new ClassPathXmlApplicationContext("config/applicationContext_DI.xml");
Student s = (Student)context.getBean("s1");
System.out.println(s);
}

 


setter方法注入----普通字符串


 

2.通过setter的方法进行依赖注入(推荐)

xml(普通字符串)

<!-- 1、注入的普通字符串 -->
<bean id="a1" class="com.linge.d_DI_setter.Admin">
<!-- 这里的name找的是JavaBean中的setter的方法名称:只是把set这三个字符串去掉,把首字母小写 -->
<property name="nameStr" value="小布"></property>
</bean>

 

javaBean

public class Admin {
private String name;//字符串
//提供相应的setter的方法
public void setNameStr(String name) {
this.name = name;
}

 


setter注入----注入javaBean


注入JavaBean

public class Gender {

//通过setter的方法注入普通的字符串
private String gender;
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Gender [gender=" + gender + "]";
}

 

xml注入javaBean

<bean id="gender1" class="com.linge.d_DI_setter.Gender">
<property name="gender" value="人妖"></property>
</bean>
<bean id="a2" class="com.linge.d_DI_setter.Admin">
<property name="nameStr" value="小布"></property>
<property name="ageStr" value="18"></property>
<property name="gender" ref="gender1"></property>
</bean>

 

 

测试方法

public static void main(String[] args) {
		ApplicationContext  context = new ClassPathXmlApplicationContext("/applicaionContex.DI.xml");
		Object b = context.getBean("zz");
		System.out.println(b);
	}

 

 

3、基于命名空间

p-namespace (property)

   xmlns:p="http://www.springframework.org/schema/p"

<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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean name="john-classic" class="com.example.Person">
        <property name="name" value="John Doe"/>
        <property name="spouse" ref="jane"/>
    </bean>

    <bean name="john-modern"
        class="com.example.Person"
        p:name="John Doe"
        p:spouse-ref="jane"/>

</beans>

c-namespace (constructor-arg)

  xmlns:c="http://www.springframework.org/schema/c"

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:c="http://www.springframework.org/schema/c"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="beanTwo" class="x.y.ThingTwo"/>
    <bean id="beanThree" class="x.y.ThingThree"/>

    <!-- traditional declaration with optional argument names -->
    <bean id="beanOne" class="x.y.ThingOne">
        <constructor-arg name="thingTwo" ref="beanTwo"/>
        <constructor-arg name="thingThree" ref="beanThree"/>
        <constructor-arg name="email" value="something@somewhere.com"/>
    </bean>

    <!-- c-namespace declaration with argument names -->
    <bean id="beanOne" class="x.y.ThingOne" c:thingTwo-ref="beanTwo"
        c:thingThree-ref="beanThree" c:email="something@somewhere.com"/>

</beans>

四、@Lookup注入

主要针对已经单例的实例A中与其他实例B组合,B需要多个实例的情况。

方式一

引入ApplicationContext每次调用方法时用上下文的getBean(name,class)方法去重新获取bean B的实例。

正如官方文档例子    则过于耦合代码

public class CommandManager implements ApplicationContextAware {

    private ApplicationContext applicationContext = null;

    public Object process(Map commandState) {
        // grab a new instance of the appropriate Command
        Command command = createCommand();
        // set the state on the (hopefully brand new) Command instance
        command.setState(commandState);
        return command.execute();
    }

    protected Command createCommand() {
        // notice the Spring API dependency!
        return this.applicationContext.getBean("command", Command.class);
    }

    public void setApplicationContext(
            ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

方式二

  使用@Lookup 注解注入

public abstract class CommandManager {


    public Object process(Map commandState) {
        // grab a new instance of the appropriate Command
        Command command = createCommand();
        // set the state on the (hopefully brand new) Command instance
        command.setState(commandState);
        return command.execute();
    }

    @Lookup
    protected abstract Command createCommand() ;



}

Tips:  被注入的方法需要满足以下格式

<public|protected> [abstract] <return-type> theMethodName(no-arguments);

 

lookup代码示例地址

这样获取的内部实例就会满足我们的需求

 

ps:在翻查笔记的过程中,当时居然还写了一些spring2.5,3.0的新特性----简化setter方法的注入,其实本人觉得好像意义不大,下篇带过