Spring框架--IOC详解+代码简单实例

本文介绍了Spring框架作为开源的轻量级容器,重点讲解了IoC和DI的概念,以及如何通过Set注入动态解决代码耦合问题。通过配置文件和依赖注入实例,展示了Spring的Bean管理、构造器注入和Set方式的DI应用。
摘要由CSDN通过智能技术生成

官方文档:https://spring.io/projects/spring-framework#overview
官方下载地址:https://repo.spring.io/ui/native/release/org/springframework/spring/

优点

  • Spring是一个开源的免费的框架(容器)!
  • Spring是一个轻量级的、非入侵式的框架!
  • 控制反转(IOC)、面向切面编程(AOP)!
  • 支持事务的处理、对框架整合的支持!

总结一句话:Spring就是一个轻量级控制反转面向切面编程 的框架

IoC(Inversion of Control),是一种设计思想,**DI(依赖注入)**是实现IoC得一种方法。

IOC理论推导
一般业务流程:
1.UserDAO层
2.UserDAOImpl实现层
3.UserService接口
4.UserImpl实现类
实例:
1、

public interface UserDao {
    void getUser();
}

2、

public class UserDaoImpl implements UserDao{
    @Override
    public void getUser() {
        System.out.println("实现sql");
    }
}

3、

public interface UserService {
    void getUser();
}

4、

    private UserDao userDao = new UserDaoImpl();
    private UserDao userDao =new UserDaoMysqlImpl();
    @Override
    public void getUser() {
        userDao.getUser();
    }

5:测试、

public class MyTest {
    public static void main(String[] args) {

        UserService userService = new UserServiceImpl();
        userService.getUser();
    }
}

在之前的业务中用户的需求可能会影响原来的代码,我们需要根据用户的需求修改原来的代码,比如在dao层中增加多个实现类
2+、

public class UserDaoMysqlImpl implements UserDao{
    @Override
    public void getUser() {
        System.out.println("实现Mysql");
    }
}

public class UserDaoOracleImpl implements UserDao{
    @Override
    public void getUser() {
        System.out.println("实现Oracle");
    }
}

则UserServiceImpl也需要每次跟着修改

	private UserDao userDao = new UserDaoImpl();
    private UserDao userDao = new UserDaoMysqlImpl();
    @Override
    public void getUser() {
        userDao.getUser();
    }

每次增加都会需要不断修改
修改的成本代价十分昂贵!

我们使用一个Set接口实现,已经发生了革命性的变化!
在UserServiceImpl实现类中利用Set进行动态实现值得注入

public class UserServiceImpl implements UserService {
    /*
     * 修改之前,测试每次都需要更改 实现类
     *
     * */
//    private UserDao userDao = new UserDaoImpl();
//    private UserDao userDao = new UserDaoMysqlImpl();
//    @Override
//    public void getUser() {
//        userDao.getUser();
//    }

    /*
     * 修改之后,利用set进行动态实现值的注入
     *
     * */
    private UserDao userDaoAfter;

    public void setUserDaoAfter(UserDao userDaoAfter) {
        this.userDaoAfter = userDaoAfter;
    }

    public void getUser() {
        userDaoAfter.getUser();
    }
}

实现类

public class MyTest {
    public static void main(String[] args) {

//        UserService userService = new UserServiceImpl();
//        userService.getUser();

        UserService userService = new UserServiceImpl();
        ((UserServiceImpl) userService).setUserDaoAfter(new UserDaoMysqlImpl());
        userService.getUser();
    }
}

之前,程序式主动创建对象!控制权在程序员手上!
使用set注入后,主动权放在了程序身上,而是变成了被动得接收对象
这种思想,从本质上解决了问题,程序员不用再去管理对象得创建,可以更加专注在业务得实现,系统降低了耦合性。这是IOC得原型!

使用配置文件

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- 使用spring来创建对象,在spring这些都称为Bean

        类型 变量名 = new 类型;

        bean = 对象  new Hello();

        id = 变量名
        class = new 的对象
        property = 相当于给对象中的属性设置一个值
    -->

    <bean id="hello" class="helloSpring.pojo.Hello">
        <property name="hello" value="Spring"/>
    </bean>

    <bean id="sqlImpl" class="oneIOC.dao.UserDaoImpl"/>
    <bean id="mysqlImpl" class="oneIOC.dao.UserDaoMysqlImpl"/>
    <bean id="userServiceImpl" class="oneIOC.service.UserServiceImpl">
        <!--ref :引用Spring容器中创建好的对象-->
        <property name="userDaoAfter" ref="mysqlImpl"/>
    </bean>
</beans>

测试:

public class MyTest {
    public static void main(String[] args) {
        //获取ApplicationContext;
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        //容器在手,天下我有,用什么就直接get什么
         UserServiceImpl userServiceImpl = (UserServiceImpl)context.getBean("userServiceImpl");
         userServiceImpl.getUser();
    }
}

IoC创建对象的方式
在这里插入图片描述

@Data
@AllArgsConstructor
public class User {
    private String name;

    public void show(){
        System.out.println("name"+name);
    }
}

1.使用无参构造创建对象,默认!
2.假设我们要使用有参构造创建对象。
          1.下标赋值

  <!--下标赋值-->
    <bean id="user" class="oneIOC.pojo.User">
        <constructor-arg index="0" value="jack"/>
    </bean>

          2.通过类型创建,不建议使用

 <!--类型赋值 不建议使用-->
    <bean id="user" class="oneIOC.pojo.User">
        <constructor-arg type="java.lang.String" value="jack"/>
    </bean>

          3.直接通过参数名

  <!--直接通过参数名-->
    <bean id="user" class="oneIOC.pojo.User">
        <constructor-arg name="name" value="jack"/>
    </bean>

总结:在配置文件加载的时候,容器中管理的对象就已经初始化了!

<!--起的别名 -->
    <alias name="user" alias="erwe"/>
    
<!--id是bean的唯一标识符,也就是相当于我们学的对象名
    class: bean 对象对应的全限定名: 包名 + 类型
    name:也是别名,而且name 可以同时取多个别名-->
name="user2 u2,u3;u4

import

一般用于团队开发,它可以将多个配置文件,导入合并为一个,加入不同类需要不同的bean文件。此时可以使用

   <import resource="beans.xml"/>
   <import resource="beans2.xml"/>

DI依赖注入

构造器注入
Set方式注入【重点】
  • 依赖注入:Set注入
        - 依赖:bean对象的创建依赖于容器!
        - 注入:bean对象中的所有属性,由容器来注入!
    【环境搭载】
    1.复杂类型
@Data
public class Address {
    private String address;
}

2.真实对象

@Data
public class Student {
    private String name;
    private Address address;
    private String[]books;
    private List<String> hobbies;
    private Map<String,String> card;
    private Set<String> games;
    private String wife;
    private Properties info;
}

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


    <bean id="address" class="diIoC.pojo.Address"/>
    <bean id="student" class="diIoC.pojo.Student">
        <!--第一种,普通注入 -->
        <property name="name" value="Oh嘻嘻嘻嘻"/>
        <!--bean注入,ref-->
        <bean id="address" class="diIoC.pojo.Address">
        <property name="address" value="东山"/>
    </bean>
        <!--数组注入 ,ref-->
        <property name="books">
            <array>
                <value>红楼梦</value>
                <value>西游记</value>
                <value>假面山庄</value>
            </array>
        </property>
        <!--List-->
        <property name="hobbies">
            <list>
                <value>跑步</value>
                <value>睡觉</value>
                <value>手工</value>
            </list>
        </property>
        <!--Map-->
        <property name="card">
            <map>
                <entry key="身份证" value="11111111111111"/>
                <entry key="银行卡" value="9999999999999999"/>
            </map>
        </property>
        <!--Set-->
        <property name="games">
            <set>
                <value>王者荣耀</value>
                <value>和平精英</value>
            </set>
        </property>
        <property name="wife">
            <null/>
        </property>
        <property name="info">
            <props>
                <prop key="学号">2018</prop>
                <prop key="性别"></prop>
            </props>
        </property>
    </bean>
</beans>

4.测试类

public class diIoCTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beandi.xml");
        Student student = (Student)context.getBean("student");
        System.out.println(student.toString());
    }
}

Student(name=Oh嘻嘻嘻嘻, 
address=Address(address=东山), 
books=[红楼梦, 西游记, 假面山庄],
hobbies=[跑步, 睡觉, 手工],
card={身份证=11111111111111, 银行卡=9999999999999999},
games=[王者荣耀, 和平精英],
wife=null, 
info={学号=2018, 性别=})

P命名 | C命名

不能直接使用需要导入

<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"
       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">

    <!--p命名空间注入,可以直接注入属性的值 property-->
    <bean id="user" class="diIoC.pojo.User" p:name="小崽子" p:age="18"/>

    <!--c命名空间注入,通过构造器注入,全参构造器 可以-->
    <bean id="user1" class="diIoC.pojo.User" c:name="哼哼" p:age="28"/>

</beans>

** 注意:c命名空间注入,必须有全参构造器 **

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private String name;
    private int age;
}

bean作用域

1.单例模式(Spring默认机制)

<!--单例模式,Spring默认机制-->
    <bean id="user1" class="diIoC.pojo.User" c:name="哼哼" p:age="28" scope="singleton"/>

2.原型模式:每次从容器中get的时候,都会产生一个新的对象!

<!--原型模式-->
    <bean id="user1" class="diIoC.pojo.User" scope="prototype"/>

3.其余的request、session、application/这些个只能在web开发中使用到

Bean自动装配

  • 自动装配式Spring满足bean依赖的一种方式
  • Spring会在上下文中自动寻找,并自动给bean装配属性
  • 隐式的自动装配bean【重要】
@Data
@AllArgsConstructor
@NoArgsConstructor
public class People {
    private String name;
    private Dog dog;
    private Cat cat;
}

public class Dog {
    public void shout(){
        System.out.println("wang~");
    }
}

public class Cat {
    public void shout(){
        System.out.println("miao~");
    }
}

    <bean id="cat" class="autowireBean.pojo.Cat"/>
    <bean id="dog" class="autowireBean.pojo.Dog"/>

    <!-- byName 会自动在容器上下文中查找,和自己对象set方法后边的值对应的beanid
         byType 会自动在容器上下文中查找,和自己对象属性类型后边的值对应beanid!
        -->
<!--    <bean id="people" class="autowireBean.pojo.People" autowire="byName">-->
    <bean id="people" class="autowireBean.pojo.People" autowire="byType">
        <property name="name" value="我是你的神"/>
    </bean>

测试

public class AutoWireTest {
    @Test
    public void test(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("autowireBean.xml");
        People people = context.getBean("people",People.class);
        people.getCat().shout();
        people.getDog().shout();

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不想当个程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值