既然想要理解原理 那尽头即是语文

IOC 控制反转

先说一下大致笼统的:
由用户管理Bean 转变为 框架管理Bean
框架即是 IOC Container

Bean就相当于一个组件 调用它实现相应功能


Ioc即“控制反转”,不是什么技术,而是一种设计思想

控制
不再进行new创建对象 而是IOC容器控制对象的创建

反转
容器帮忙创建及注入依赖对象

优点:
使代码松散耦合

image

image

看一个例子:

Dao:

public interface UserDao {
    void getUser();
}

public class UserImpl implements UserDao{
    public void getUser() {
        System.out.println("获取用户数据");
    }
}
Service:

public interface UserService {
    void getUser();
}


public class UserServiceImpl implements UserService {
    private UserDao userDao;

    //  注入
    public void setUserDao(UserDao userDao){
        this.userDao=userDao;
    }

    //写死 传统下:
   //    private UserDao userDao = new UserImpl();

    public void getUser() {
        userDao.getUser();
    }
}
假如数据源很多需要实现的服务很多
<?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="mysql" class="dao.UserImplMysql"/>
    <bean id="other" class="dao.UserImplOtherSQl"/>
    <bean id="UserServiceImpl" class="Service.UserServiceImpl">
<!--        ref  应用spring容器中创建好的对象-->
<!--        value 具体的值-->
        <property name="userDao" ref="mysql"/>
    </bean>
</beans>
import Service.UserService;
import Service.UserServiceImpl;
import dao.UserImpl;
import dao.UserImplMysql;
import dao.UserImplOtherSQl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Daotest {
    public static void main(String[] args) {
        //用户实际调用的是业务层 dao层不接触
        UserServiceImpl userService = new UserServiceImpl();
//
//
//        userService.setUserDao(new UserImplMysql());
//        userService.setUserDao(new UserImplOtherSQl());
//        userService.getUser();

        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        UserServiceImpl userServiceImpl = (UserServiceImpl) context.getBean("UserServiceImpl");
        userServiceImpl.getUser();


    }
}

不用再一个一个new创建调用 而是直接beans.xml配置好 然后直接使用


首先 配置Bean

  1. xml
  2. java
  3. 注解

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

<!--    spring中创建对象 都用作Bean-->
<!--    等同于new 一个对象-->
    <bean id="hello" class="pojo.Hello">
        <property name="name" value="高低远近"/>
    </bean>

</beans>

优点: 可以使用于任何场景,结构清晰,通俗易懂

缺点: 配置繁琐,不易维护,枯燥无味,扩展性差

2. java

@Configuration注解声明为配置类
@Bean 标记实例 交给Spring管理
优点:适用于任何场景,配置方便,因为是纯Java代码,扩展性高,十分灵活

缺点:由于是采用Java类的方式,声明不明显,如果大量配置,可读性比较差

3. 注解

  1. @Component
    标记一个普通的Spring组件类
    通过()可替代后三个
  2. @Controller
    MVC控制器类 跳转
  3. @Service
    业务服务类
  4. @Repository
    标记Dao类

优点:开发便捷,通俗易懂,方便维护。

缺点:具有局限性,对于一些第三方资源,无法添加注解。只能采用XML或JavaConfig的方式配置


DI 依赖注入 实现方式

  1. 构造器注入
  2. setter注入
  3. 注解注入
    直接看例子:
pojo实体类:
package pojo;

public class User {
    public User(String name) {
        this.name = name;
    }

    private String name;

    public String getName() {
        return name;
    }

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

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

构造器方式配置Bean 注意pojo类中要有有参构造方法

<?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="user" class="pojo.User" name="users,users2 users3;users4">
<!--     <property name="name" value="高地远近"/>-->
<!--     <constructor-arg index="0" value="高地远近"/>-->
     <constructor-arg type="java.lang.String" value="高远"/>
 </bean>
    <alias name="user" alias="other_name"/>
</beans>
测试:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pojo.User;

public class TTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        User user = (User) context.getBean("user");
        User user1 = (User) context.getBean("other_name");
        User user2 = (User) context.getBean("users");
        User user3 = (User) context.getBean("users2");
        User user4 = (User) context.getBean("users3");
        User user5 = (User) context.getBean("users4");
        user.show();
        user1.show();
        user2.show();
        user3.show();
        user4.show();
        user5.show();
    }
}

pojo实体类:
package pojo;

import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

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;
    //Properties 继承于 Hashtable,用于管理配置信息的类。
//由于 Properties 继承自 Hashtable 类,因此具有 Hashtable 的所有功能,同时还提供了一些特殊的方法来读取和写入属性文件。
//Properties 类常用于存储程序的配置信息,例如数据库连接信息、日志输出配置、应用程序设置等。
// 使用Properties类可以将这些信息存储在一个文本文件中,并在程序中读取这些信息。
    private Properties info;
    private String wife;

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

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

    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 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 Properties getInfo() {
        return info;
    }

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

    public String getWife() {
        return wife;
    }

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

    @Override
    public String toString() {
        return "student{" +
                "name='" + name + '\'' +
                ", address=" + address.toString() +
                ", hobbies=" + hobbies +
                ", card=" + card +
                ", games=" + games +
                ", info=" + info +
                ", wife='" + wife + '\'' +
                '}';
    }
}


setter注入:

<?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="pojo.Address">
        <property name="addr" value="河北"/>
    </bean>
    <bean id="student" class="pojo.Student">
        <!--        值注入-->
        <property name="name" value="高远"/>
        <!--        bean注入-->
        <property name="address" ref="address"/>
        <!--        数组注入-->
        <property name="books">
            <array>
                <value>啊啊啊</value>
                <value>sda</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="id卡" value="1111"/>
                <entry key="英航卡" value="2222"/>
                <entry key="萨达" value="3333"/>
            </map>
        </property>
<!--        set注入-->
        <property name="games">
            <set>
                <value>cf</value>
                <value>cs</value>
                <value>pubg</value>
            </set>
        </property>
<!--        null注入-->
        <property name="wife">
            <null/>
        </property>
<!--        Properties注入-->
        <property name="info">
    <props>
        <prop key="学号">222020</prop>
        <prop key="id">5555</prop>
        <prop key="电话">555555</prop>
    </props>
        </property>
    </bean>

</beans>
测试:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pojo.Student;

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

    }
}


注解注入:

package pojo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import javax.annotation.Resource;


/**
 *     @Resource
 *     byName默认和byType
 *
 *     @Autowired
 *     byType默认和byName 唯一一个
 * */


public class People {
    //required=false 对象可以为空
//    @Autowired(required = false)
    @Resource
    private Cat cat;
    @Autowired
    @Qualifier(value = "dog222")
    private Dog dog;
    private String name;

    @Override
    public String toString() {
        return "People{" +
                "cat=" + cat +
                ", dog=" + dog +
                ", name='" + name + '\'' +
                '}';
    }

    public void setCat(Cat cat) {
        this.cat = cat;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }

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

    public Cat getCat() {
        return cat;
    }

    public Dog getDog() {
        return dog;
    }

    public String getName() {
        return name;
    }
}

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

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

<!--    <bean id="people" class="pojo.People" p:cat-ref="cat" p:dog-ref="dog" p:name="高远">-->
<!--    autowire自动装配-->
<!--    <bean id="people" class="pojo.People" autowire="byName" p:name="高远">-->
<!--    <bean id="people" class="pojo.People" autowire="byType" p:name="高远">-->
    <bean id="people" class="pojo.People"  p:name="高远">
    </bean>
    <context:annotation-config/>

</beans>


<!--        2. "byName"-->
<!--        Autowiring by property name. If a bean of class Cat exposes a "dog"-->
<!--        property, Spring will try to set this to the value of the bean "dog"-->
<!--        in the current container. If there is no matching bean by name, nothing-->
<!--        special happens.-->

<!--        3. "byType"-->
<!--        Autowiring if there is exactly one bean of the property type in the-->
<!--        container. If there is more than one, a fatal error is raised, and-->
<!--        you cannot use byType autowiring for that bean. If there is none,-->
<!--        nothing special happens.-->
测试:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pojo.People;

public class Mytest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        People people = context.getBean("people", People.class);
        people.getDog().shout();
        people.getCat().shout();
    }
}

@Autowired和@Resource以及@Inject等注解注入有何区别

1、@Autowired是Spring自带的,@Resource是JSR250规范实现的,@Inject是JSR330规范实现的
2、@Autowired、@Inject用法基本一样,不同的是@Inject没有required属性
3、@Autowired、@Inject是默认按照类型匹配的,@Resource是按照名称匹配的
4、@Autowired如果需要按照名称匹配需要和@Qualifier一起使用,@Inject和@Named一起使用,@Resource则通过name进行指定

参考:
https://pdai.tech/md/spring/spring-x-framework-ioc.html
https://segmentfault.com/a/1190000022016826

posted on 2024-05-18 10:00  蒸饺  阅读(23)  评论(0)    收藏  举报