IOC(控制反转)和DI(依赖注入)

2. IoC(控制反转)的概念和作用 DI(依赖注入)

控制反转是通过依赖注入实现的。

IOC是指原先我们代码里面需要实现对象的创建、维护对象的依赖关系,反转给容器帮忙实现。那么就需要创建一个容器,同时需要一种描述来让容器知道需要创建的对象与对象的关系。依赖注入的目的是为了解耦,体现一种组合的“理念”。继承一个父类,子类将于父类耦合,组合关系使耦合度大大降低。

耦合性(Coupling),也叫耦合度,是对模块间关联程度的度量。耦合的强弱取决于模块间接口的复杂性、调用模块的方式以及通过界面传送数据的多少。模块间的耦合度是指模块之间的依赖关系,包括控制关系、调用关系、数据传递关系。模块间联系越多,其耦合性越强,同时表明其独立性越差( 降低耦合性,可以提高其独立性)。软件设计中通常用耦合度和内聚度作为衡量模块独立程度的标准。划分模块的一个准则就是高内聚低耦合。

Spring IOC 容器负责创建Bean,并通过容器将Bean注入到需要的Bean对象上。同时Spring IOC容器还负责维护Bean对象与Bean对象之间的关系。那么,Spring IOC如何来体现对象与对象之间的关系呢?Spring提供XML配置和Java配置等方式。下面来个例子:

User 实体被UserDao,UserService和UserServlet所依赖

实现这些类:

UserDao:

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.util.*;

@AllArgsConstructor
@Data
@NoArgsConstructor
@ToString
public class User {
    private int id;
    private String name;
    private int age;
    private char sex;
    //List集合
    private List<String> photos;

    private String[] friends;

    private Set<String> money;

    private Map<String,String> map;

    private Properties properties;
}

UserDao

import lombok.Setter;

@Setter
public class UserDao {
    private String url;
    private String driverClass;
    private String username;
    private String password;

    public User findUser(){
        User u = new User (1000,"张三",21,'M',null,null,null,null,null);
        return u;
    }
}

UserSerivce

import lombok.Data;

@Data
public class UserService {
    private UserDao userDao = null;

    public User findUser () {
        return userDao.findUser ();
    }
}

UserServlet

import lombok.Data;

@Data
public class UserServlet {
    private UserService userService;
    public void findUser(){
        System.out.println ("spring工厂的实例:");
        System.out.println (userService.findUser());
    }
}

在pomxml中添加Spring 核心库的依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>edu.xatu</groupId>
    <artifactId>IOC</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.8</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.1.9.RELEASE</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.1.9.RELEASE</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.9.RELEASE</version>
        </dependency>

</project>

创建配置文件applicationContext.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="userServlet" class="edu.xatu.UserServlet" scope="singleton"><!--scope="singleton" singleton单例  scope="prototype"多例-->
        <property name="userService" ref="service"/>
    </bean>

    <bean id="service" class="edu.xatu.UserService" autowire="byType"><!--autowire="byType"表示根据类型自动注入,但是只能有一个类型,不然无法区分-->
        <!--<property name="userDao" ref="userDao"/>-->
    </bean>
    <bean class="edu.xatu.UserDao" id="userDao">
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/cms"/>
        <property name="username" value="root"/>
        <property name="password" value=""/>
    </bean>
    <bean id="user" class="edu.xatu.User">
       <!-- <constructor-arg value="1111"/>
        <constructor-arg value="张三"/>
        <constructor-arg value="20"/>
        <constructor-arg value="M"/>-->
        <property name="photos">
            <list>
                <value>1.jpg</value>
                <value>2.jpg</value>
                <value>3.jpg</value>
                <value>4.jpg</value>
            </list>
        </property>
        <property name="friends">
            <array>
                <value>张三</value>
                <value>李四</value>
                <value>王阿门</value>
                <value></value>
            </array>
        </property>
        <property name="money">
            <set>
                <value>人民币</value>
                <value>美元</value>
                <value>日元</value>
                <value>欧元</value>
                <value>英镑</value>
            </set>
        </property>
        <property name="map">
            <map>
                <entry key="A" value="aaa"></entry>
                <entry key="B" value="bbb"></entry>
                <entry key="C" value="ccc"></entry>
                <entry key="D" value="ddd"></entry>
            </map>
        </property>
        <property name="properties">
            <props>
                <prop key="22">nscbhj</prop>
                <prop key="27">djbschj</prop>
                <prop key="24">5156</prop>
                <prop key="65"></prop>
            </props>
        </property>
    </bean>

    <bean id="factorybean" class="edu.xatu.FactoryBean"/>
    <bean id="mybean" factory-bean="factorybean" factory-method="createUser"/>

    <!--利用静态工厂bean方法创建实例-->
    <bean id="factory1" class="edu.xatu.FactoryBean" factory-method="createStaticUser"/>

</beans>

创建FactoryBean类:

public class FactoryBean {
    /**
     * 非静态方法(实例方法)
     */
    public User createUser(){
        return new User (  );
    }

    /**
     * 静态方法
     */
    public static User createStaticUser(){
        User u = new User (1000,"张三",21,'M',null,null,null,null,null);
        return u;
    }
}

测试类Test

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    public static void main (String[] args) {
        //创建工厂
        BeanFactory factory = new ClassPathXmlApplicationContext ( "applicationContext.xml" );
        //根据Bean的id找Bean
        UserServlet servlet = (UserServlet) factory.getBean ( "userServlet" );
        UserServlet servlet1 = (UserServlet) factory.getBean ( "userServlet" );
        System.out.println (servlet == servlet1);
        System.out.println (factory.getBean ( "user" ));
        servlet.findUser ();
    }
}

测试结果:

true
User(id=0, name=null, age=0, sex= , photos=[1.jpg, 2.jpg, 3.jpg, 4.jpg], friends=[张三, 李四, 王阿门,], money=[人民币, 美元, 日元, 欧元, 英镑], map={A=aaa, B=bbb, C=ccc, D=ddd}, properties={27=djbschj, 24=5156, 22=nscbhj, 65=})
spring工厂的实例:
User(id=1000, name=张三, age=21, sex=M, photos=null, friends=null, money=null, map=null, properties=null)

这是怎么实现的呢?

首先是在main函数中根据applicationContext.xml创建工厂

 BeanFactory factory = new ClassPathXmlApplicationContext ( "applicationContext.xml" );

接着根据applicationContext.xml中的bean 属性中的id值userServlet,找到类UserServlet,工厂通过反射实例化,同理其他方法也是如此。

    <bean id="userServlet" class="edu.xatu.UserServlet" scope="singleton"><!--scope="singleton" singleton单例  scope="prototype"多例-->
        <property name="userService" ref="service"/>
    </bean>
    <bean id="service" class="edu.xatu.UserService" autowire="byType"><!--autowire="byType"表示根据类型自动注入,但是只能有一个类型,不然无法区分-->
        <property name="userDao" ref="userDao"/>
    </bean>
    <bean class="edu.xatu.UserDao" id="userDao">
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/cms"/>
        <property name="username" value="root"/>
        <property name="password" value=""/>
    </bean>
    <bean id="user" class="edu.xatu.User">
       <!-- <constructor-arg value="1111"/>
        <constructor-arg value="张三"/>
        <constructor-arg value="20"/>
        <constructor-arg value="M"/>-->
        <property name="photos">
           ...

实例化完成后,就进行逻辑处理。

2.1注解:

@Compent 没有明确的注解

@Controller 主要用到web(控制层)

@Service 服务service(业务逻辑)层

@Repository 数据访问层 dao层

@Autowired 默认按类型装配。默认情况下要求依赖对象必须存在,如果允许为null值,可以设置它的required属性为false,如:@Autowired(required=false)

@Qualifier(“ser”) 和@Autowired结合使用,根据名称进行装配

@Resource相当中@Autowired加@Qualifier(“ser”),即可根据类型进行装配,也可以根据名称进行装配

2.2pom.xml

配置的依赖是各种组件的坐标,例如:

<dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.8</version>
        </dependency>

写在这个文件里面的依赖,idea会从中央库下载这些组件。

2.3lombok组件

Lombok能以简单的注解形式来简化java代码,提高开发人员的开发效率。

@Setter就代替了生成出来的Setter方法,以下同理
@Data
@Value
@ToString
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
@RequiredArgsConstructor
@Getter
发布了101 篇原创文章 · 获赞 49 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Austin_/article/details/102059914