0
点赞
收藏
分享

微信扫一扫

Spring详解

谁知我新 2022-04-18 阅读 41
javaspring

1. IOC

1.1 拓展

现代化的Java开发,就是基于Spring的开发

  • SpringBoot
    • 快速开发的脚手架
    • 基于SpringBoot可以快速开发微服务
    • 约定大于配置
  • SpringCloud
    • SpringCloud是基于SpringBoot实现的

学习SpringBoot的前提是掌握Spring以及SpringMVC,SpringBoot起到承上启下 的作用;

弊端:配置十分繁琐,人称:“配置地狱”;

1.2 IOC理论推导

问题展示

对象包:(接口)

package com.kangzhu.dao;
public interface UserDao {
    public void getUser();
}

对象包:(实现1)

package com.kangzhu.dao;
public class UserDaoImpl implements UserDao{
    @Override
    public void getUser() {
        System.out.println("I am the user");
    }
}

对象包:(实现2)

package com.kangzhu.dao;
public class UserDaoMysqlImpl implements UserDao{
    @Override
    public void getUser() {
        System.out.println("I am the user found by Mysql");
    }
}

服务包:(接口)

package com.kangzhu.service;
public interface UserService {
    public void getUser();
}

服务包:(实现)

package com.kangzhu.service;
import com.kangzhu.dao.UserDao;
import com.kangzhu.dao.UserDaoImpl;
import com.kangzhu.dao.UserDaoMysqlImpl;

public class UserServiceImpl implements UserService{
//    private UserDao userDao = new UserDaoImpl();
    private UserDao userDao = new UserDaoMysqlImpl();
    @Override
    public void getUser() {
//        业务层调用dao层
        userDao.getUser();
    }
}

客户端(测试类)

import com.kangzhu.service.UserServiceImpl;
public class MyTest {
    public static void main(String[] args) {
//        用户实际调用的是业务层
        UserServiceImpl userService = new UserServiceImpl();
        userService.getUser();
    }
}

问题在哪呢?

客户端的需求可能会影响我们的代码,如果说客户端想要通过普通的方式查询用户,服务包:(实现)中需要引入对象包(实现1),如果客户端想要通过Mysql的方式查询用户,需要引入对象包(实现2);

需要根据客户端的需求修改源代码,如果代码量很大,修改一次的成本就会十分昂贵!

解决方法(set注入)

改变服务实现类

package com.kangzhu.service;
import com.kangzhu.dao.UserDao;
public class UserServiceImpl implements UserService{
    private UserDao userDao = null;
    // set注入
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    @Override
    public void getUser() {
        userDao.getUser();
    }
}

客户端:

import com.kangzhu.dao.UserDaoMysqlImpl;
import com.kangzhu.service.UserServiceImpl;

public class MyTest {
    public static void main(String[] args) {
//        用户实际调用的是业务层
        UserServiceImpl userService = new UserServiceImpl();
        userService.setUserDao(new UserDaoMysqlImpl());
        userService.getUser();
    }
}
  • 之前,程序是主动对象,控制权在程序员手上;
  • 使用了set注入后,程序不再具有主动性,而是变成了接收对象;

这种思想从本质上解决了问题,程序员不用再去管理对象的创建;系统的耦合性降低,程序员可以专注在业务实现上;

这就是IOC的原型!

IOC的本质

  • 控制反转,是一种设计思想;
  • 所谓控制反转就是:获得依赖对象的方式反转了;

2. HelloSpring

  1. 编写实体类

    package com.kangzhu.pojo;
    
    public class Hello {
        private String str;
        public String getStr() {
            return str;
        }
        public void setStr(String str) {
            this.str = str;
        }
        @Override
        public String toString() {
            return "Hello{" +
                    "str='" + str + '\'' +
                    '}';
        }
    }
    
  2. 添加配置文件(名称任意,这里是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
           http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    
    <!--使用Spring来创建对象,在Spring这些都称为Bean
        类型 变量名 = new 类型();
    
        id = 变量名
        class = new的对象
        property 相当于给对象中的属性设置一个值
    -->
        <bean id="hello" class="com.kangzhu.pojo.Hello">
            <property name="str" value="Spring"/>
        </bean>
    </beans>
    
  3. 测试

    import com.kangzhu.pojo.Hello;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MyTest {
        public static void main(String[] args) {
    //        获取Spring的上下文对象
            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    //        我们的对象都在Spring中管理了,我们要使用,直接去里面取出来就可以了
            Hello hello = (Hello) context.getBean("hello");
            System.out.println(hello.toString());
        }
    }
    

控制:传统应用程序对象是由程序控制创建的,使用Spring后,对象是由Spring来创建的;

反转:程序本身不创建对象,而变成被动的接收对象

3. IOC创建对象方式

  1. 使用无参构造创建对象,默认

  2. 使用有参构造创建对象

    • 下标赋值

      <bean id="user1" class="com.kangzhu.pojo.User">
          <constructor-arg index="0" value="kangzhu1"/>
      </bean>
      
    • 根据参数类型赋值

      <!--但是假设有两个参数的类型相同,这种方式不适用-->
      <bean id="user2" class="com.kangzhu.pojo.User">
      <constructor-arg type="java.lang.String" value="kangzhu2"/>
      </bean>
      
    • 根据参数名赋值

      <bean id="user3" class="com.kangzhu.pojo.User">
          <constructor-arg name="name" value="kangzhu3"/>
      </bean>
      

4. Spring配置

4.1 别名

<alias name="user" alias="aliasUser"/>

这里的name是bean中的id,也就是对象名,alias是别名;

4.2 Bean的配置

id:bean的唯一标识符,也就是对象名;

class:bean对象所对应的权限命名(包名.类名);

name:也是别名,而且name更高级,可以同时取多个别名(不同别名间通过空格,逗号,分号等等进行分割);

4.3 import

import一般用于团队开发使用,它可以将多个配置文件导入合并为一个;

假设项目中有多个人开发,这三个人负责不同的类开发,不同的类需要注册在不同的bean中,我们可以利用import将所有人的beans.xml合并为一个总的;

  • programmer1 --> beans1.xml
  • programmer2 --> beans2.xml
  • programmer3 --> beans3.xml

总的是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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <import resource="beans1.xml"/>
    <import resource="beans2.xml"/>
    <import resource="beans3.xml"/>

</beans>

如果说遇到相同的对象名,后面的会覆盖前面的;

5. 依赖注入

  • 依赖:bean对象的创建依赖于容器;

  • 注入:bean对象中的所有属性由容器注入;

5.1 构造器注入

上面的IOC创建对象方式中的使用有参构造创建对象就是构造器注入;

5.2 Set方式注入

这里创建两个实体类:

package com.kangzhu.pojo;

import java.util.*;

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;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public String[] getBooks() {
        return books;
    }

    public void setBooks(String[] books) {
        this.books = books;
    }

    public List<String> getHobbies() {
        return hobbies;
    }

    public void setHobbies(List<String> hobbies) {
        this.hobbies = hobbies;
    }

    public Map<String, String> getCard() {
        return card;
    }

    public void setCard(Map<String, String> card) {
        this.card = card;
    }

    public Set<String> getGames() {
        return games;
    }

    public void setGames(Set<String> games) {
        this.games = games;
    }

    public String getWife() {
        return wife;
    }

    public void setWife(String wife) {
        this.wife = wife;
    }

    public Properties getInfo() {
        return info;
    }

    public void setInfo(Properties info) {
        this.info = info;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", address=" + address +
                ", books=" + Arrays.toString(books) +
                ", hobbies=" + hobbies +
                ", card=" + card +
                ", games=" + games +
                ", wife='" + wife + '\'' +
                ", info=" + info +
                '}';
    }
}
package com.kangzhu.pojo;

public class Address {
    private String address;
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
}

根据数据类型来看set注入:

<?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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="address" class="com.kangzhu.pojo.Address"/>
    <bean id="student" class="com.kangzhu.pojo.Student">
<!--        第一种,基本数据类型注入-->
        <property name="name" value="kangzhu"/>

<!--        第二种,引用注入-->
        <property name="address" ref="address"/>

<!--        第三种,数组注入-->
        <property name="books">
            <array>
                <value>哈利波特</value>
                <value></value>
                <value>箱子里的人</value>
            </array>
        </property>

<!--        第四种,list注入-->
        <property name="hobbies">
            <list>
                <value>电影</value>
                <value>打游戏</value>
            </list>
        </property>

<!--        第五种,map注入-->
        <property name="card">
            <map>
                <entry key="学生卡" value="123456"/>
                <entry key="身份证" value="123456"/>
            </map>
        </property>

        <property name="games">
            <set>
                <value>LOL</value>
                <value>COC</value>
                <value>BOB</value>
            </set>
        </property>

<!--        注入为null值-->
        <property name="wife">
            <null/>
        </property>

<!--        properties注入-->
        <property name="info">
            <props>
                <prop key="学号">123</prop>
                <prop key="姓名">糠猪</prop>
            </props>
        </property>
    </bean>
</beans>

5.3 拓展方式注入

可以使用p命名空间和c命名空间进行注入:

<?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"
       xmlns:c="http://www.springframework.org/schema/c"

       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

<!--    p命名空间注入,可以直接注入属性的值-->
    <bean id="user" class="com.kangzhu.pojo.User" p:name="糠猪" p:age="18"/>

<!--    c命名空间注入-->
    <bean id="user2" class="com.kangzhu.pojo.User" c:name="糠猪2" c:age="18"/>
</beans>

note

  1. p命名空间和c命名空间不能直接使用,需要导入xml约束:

    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:c="http://www.springframework.org/schema/c"
    
  2. p代表properties,相当于set注入,c代表constructor,相当于构造器注入;

6. bean作用域

举报

相关推荐

spring:详解spring MVC

Spring JdbcTemplate详解

Spring IoC详解

spring 事务详解

Spring框架详解

Spring详解(五)

Spring全集详解

spring AOP详解

0 条评论