Spring IOC和DI

谈起Spring ,大家都听过 控制反转 依赖注入。到底什么叫控制反转,什么叫依赖注入呢。

控制反转(IOC:就是传统的方式中,我们会通过 new关键字去创建对象,由程序主动是进行对象的创建,控制对象的生命周期。控制反转就是将对象的控制权交出给 IOC容器,不在主动去创建对象,由IOC容器去创建对象,控制对象的生命周期。

依赖注入(DI):当A需要引用B对象时,在传统方式中,我们会在A中new 一个B对象,然后使用它。而依赖注入能动态的向某个对象提供它需要的对象。例如A需要B,但是A不需要创建B对象,只需要将需求告诉Spring容器,A无需知道B是怎么创建的,什么时候创建。当程序运行时,spring会在合适的时候创建一个B对象,然后像打针一样注射给A,这样A就可以依赖B对象而运行了。而DI的真正实现是依赖于反射。反射允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。

Bean的装配:基于java的显示配置,基于xml的显示配置,隐式bean扫描和自动装配。 

 

一、隐式bean扫描和自动装配

实现自动化装配 是通过组件扫描和自动装配 组合实现的。

创建类时,在类上加上@Conponent 注解,就是告诉Spring要为这个类创建bean。Spring会自动识别该注解。

例如:

package com.tzw.common;

import org.springframework.stereotype.Component;

@Component
public class GuzTrans {
    
}

当然这个需要spring扫描扫描到才能创建。所以我们需要显式配置spring的自动扫描。配置有两种方式,基于xml的配置和基于javaConfig的配置。

除了@Component注解外,还有其他的注解亦可以实现spring扫描

@Conponent 用于让Spring扫描识别,一般用于不确定的什么层的类上。

@Service ,是@Component的扩展,一般用于注解到Service层的类上。

@Controller,是@Component的扩展,一般用于web层的实现。控制层上。

@Repository,是@Component的扩展,一般用于注解到Dao层的类上。

     (1)基于xml的配置。需要<context:component-scan>,而base-package则是指定要扫描的包,包括该包和该包的子包。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">


    <context:component-scan base-package="com.tzw"></context:component-scan>

</beans>

(2)基于javaConfig配置

package com.tzw.common;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

@Configuration
@ComponentScan(basePackages = "com.tzw")
public class GuzConfig {

}

这里提到了@Configuration注解,接下来javaConfig显示装配就会用到。

(3)自动装配。以上实现了自动扫描的隐式配置,接下来要进行自动装配,说白了就是bean于bean之间的依赖关系。

实现自动装配的需要一些注解。@Autowired用来实现注入。

例如

package com.tzw.common;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class GuzService {

    @Autowired
    public GuzDao guzDao;

    public void getClientList(){
        guzDao.getClient();
    }

}






package com.tzw.common;

import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Repository
public class GuzDao {

    public List<Map<String,Object>> getClient(){
        return new ArrayList<Map<String,Object>>();
    }
}

这样就实现将 GuzDao 注入到GuzService。实现了自动装配。

@Autowired ,是spring自带的注解,是根据类型注入的。如果想用名称注入,需要搭配@qualifier。此外,还有一个required属性,用法:@Autowired(required=false),表示为如果找不到这个bean,不会抛出异常。反之,抛出异常。

@Inject,JSR330规范实现的,根据类型注入。如果想用名称注入,需要搭配@Named。

@Resource,JSR250规范实现的,按照名称匹配的。

所以使用它们需要导入不同的包。

二、javaConfig显示配置

 

这里不得不提到两个注解@Configuration 和 @Bean 

@Configuration 表明该类是配置类。@Bean会告诉Spring这个方法将会返回一个对象。

package com.tzw.javaConfig;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JavaConfig {

    @Bean
    public Client getClient(){
        return new Client();
    }

}

javaConfig方式实现注入

 两种方式:1.属性注入 2.构造方法注入;

      1.setter注入,通过set方式注入。

package com.tzw.javaConfig;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JavaConfig {

    @Bean
    public Client getClient(){

        Client client = new Client();
        client.setIdent(ident());
        return client;

    }
    @Bean
    public Ident ident(){
        return  new Ident();
    }





}
package com.tzw.javaConfig;

public class Client {


    public String clientName;

    public Ident ident;


    public String getClientName() {
        return clientName;
    }

    public void setClientName(String clientName) {
        this.clientName = clientName;
    }

    public Ident getIdent() {
        return ident;
    }

    public void setIdent(Ident ident) {
        this.ident = ident;
    }

    @Override
    public String toString() {
        return "Client{" +
                "clientName='" + clientName + '\'' +
                ", ident=" + ident +
                '}';
    }
}

2.构造器注入。通过构造方式注入。

package com.tzw.javaConfig;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JavaConfig {

    @Bean
    public Client getClient(){

        Client client = new Client(ident());
        return client;

    }
    @Bean
    public Ident ident(){
        return  new Ident();
    }





}
package com.tzw.javaConfig;

public class Client {


    public String clientName;

    public Ident ident;

    public Client(Ident ident){
        this.ident=ident;
    }

    public String getClientName() {
        return clientName;
    }

    public void setClientName(String clientName) {
        this.clientName = clientName;
    }

    public Ident getIdent() {
        return ident;
    }

    public void setIdent(Ident ident) {
        this.ident = ident;
    }

    @Override
    public String toString() {
        return "Client{" +
                "clientName='" + clientName + '\'' +
                ", ident=" + ident +
                '}';
    }
}

三、xml配置实现注入

1.setter方式注入,利用properties属性注入

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.tzw"></context:component-scan>


    <bean id="ident" class="com.tzw.javaConfig.Ident"></bean>

    <!--setter方式注入-->
    <bean id="client" class="com.tzw.javaConfig.Client">
        <property name="ident" ref="ident"></property>
    </bean>

</beans>

 2.构造方法注入,利用<constructor-arg>注入

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.tzw"></context:component-scan>


    <bean id="ident" class="com.tzw.javaConfig.Ident"></bean>

    <!--setter方式注入-->
    <!--bean id="client" class="com.tzw.javaConfig.Client">
        <property name="ident" ref="ident"></property>
    </bean>-->

    <!--构造器注入-->
    <bean id="client" class="com.tzw.javaConfig.Client">
        <constructor-arg ref="ident"></constructor-arg>
    </bean>


</beans>

 

四、混合注入

 混合注入四种方式:

1.xml配置插入xml配置,利用<import>标签

2.xml配置插入javaConfig配置,xml中通过配置<bean>,将javaConfig配置引入xml文件中

3.java配置插入java配置,通过@Import 注解引入。

4.java配置插入xml配置,通过@ImportResource注解引入。

 

1.xml 引用xml。 一个xml中bean 注入另一个xml的bean

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.tzw"></context:component-scan>


    <!--<bean id="ident" class="com.tzw.javaConfig.Ident"></bean>-->
    <!--setter方式注入-->
    <!--bean id="client" class="com.tzw.javaConfig.Client">

        <property name="ident" ref="ident"></property>
    </bean>-->
    <import resource="spring1.xml"/>
    <!--构造器注入-->
    <bean id="client" class="com.tzw.javaConfig.Client">
        <constructor-arg ref="ident"></constructor-arg>
    </bean>


</beans>

2.xml引用java配置,一个javaConfig的bean 注入xml中的bean

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.tzw"></context:component-scan>


    <!--<bean id="ident" class="com.tzw.javaConfig.Ident"></bean>-->
    <!--setter方式注入-->
    <!--bean id="client" class="com.tzw.javaConfig.Client">

        <property name="ident" ref="ident"></property>
    </bean>-->
    <bean class="com.tzw.javaConfig.IdentConfig"></bean>
    <!--构造器注入-->
    <bean id="client" class="com.tzw.javaConfig.Client">
        <constructor-arg ref="ident"></constructor-arg>
    </bean>


</beans>
package com.tzw.javaConfig;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class IdentConfig {

    @Bean
    public Ident ident(){
        return new Ident();
    }

}

3.java引用java,一个javaConfig的bean注入另一个JavaConfig的bean

package com.tzw.javaConfig;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import(IdentConfig.class)
public class JavaConfig {

    @Bean
    public Client getClient(Ident ident){

        Client client = new Client(ident);
        return client;

    }

}
package com.tzw.javaConfig;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class IdentConfig {

    @Bean
    public Ident ident(){
        return new Ident();
    }

}

4.java引用xml,通过@ImportResouce引入。不能把 xml申明的bean注入到javaConfig中

同时引用xml的配置和Java的配置。

package com.tzw.javaConfig;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportResource;

@Configuration
@ImportResource("spring1.xml")
@Import(Ident.class)
public class JavaConfig {


    @Bean
    public Client getClient(Ident ident){
        Client client = new Client(ident);
        return client;

    }

}

这样,xml中的bean和JavaConfig中的bean都会启动。但是javaConfig中的bean不能注入xml中的bean。这中方式 xml的配置和javaConfig的配置都是完整的,不能像上面那种方式混合使用。

 

五、虽然javaConfig和xml配置都可以使用,但是如果要注入的是集合,javaConfig配置就无法满足,就只能用xml配置实现。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.tzw"></context:component-scan>


    <bean id="ident" class="com.tzw.javaConfig.Ident">
        <property name="idNo" value="1"></property>
        <property name="idType" value="2"></property>
        <property name="idList">
            <list>
                <value>123456</value>
                <value>987654</value>
            </list>
        </property>
        <property name="idMap">
            <map>
                <entry key="1" value="张三"></entry>
                <entry key="2" value="李四"></entry>
            </map>
        </property>
    </bean>

</beans>

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值