当前位置: 移动技术网 > IT编程>开发语言>Java > Sping IOC学习

Sping IOC学习

2020年07月27日  | 移动技术网IT编程  | 我要评论

Sping 的简介

Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架。

Spring的特点

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

使用Spring

我们在maven的项目中只需要导入spring-webmvc架包,maven会自动为我们导入其他的依赖架包

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.8.RELEASE</version>
    </dependency>

在这里插入图片描述

Sping的七大核心模块

在这里插入图片描述
核心容器(Spring Core)

核心容器提供Spring框架的基本功能。Spring以bean的方式组织和管理Java应用中的各个组件及其关系。Spring使用BeanFactory来产生和管理Bean,它是工厂模式的实现。BeanFactory使用控制反转(IoC)模式将应用的配置和依赖性规范与实际的应用程序代码分开。

应用上下文(Spring Context)

Spring上下文是一个配置文件,向Spring框架提供上下文信息。Spring上下文包括企业服务,如JNDI、EJB、电子邮件、国际化、校验和调度功能。

Spring面向切面编程(Spring AOP)

通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring框架中。所以,可以很容易地使 Spring框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。

JDBC和DAO模块(Spring DAO)

JDBC、DAO的抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理,和不同数据库供应商所抛出的错误信息。异常层次结构简化了错误处理,并且极大的降低了需要编写的代码数量,比如打开和关闭链接。

对象实体映射(Spring ORM)

Spring框架插入了若干个ORM框架,从而提供了ORM对象的关系工具,其中包括了Hibernate、JDO和 IBatis SQL Map等,所有这些都遵从Spring的通用事物和DAO异常层次结构。

Web模块(Spring Web)

Web上下文模块建立在应用程序上下文模块之上,为基于web的应用程序提供了上下文。所以Spring框架支持与Struts集成,web模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。

MVC模块(Spring Web MVC)

MVC框架是一个全功能的构建Web应用程序的MVC实现。通过策略接口,MVC框架变成为高度可配置的。MVC容纳了大量视图技术,其中包括JSP、POI等,模型来有JavaBean来构成,存放于m当中,而视图是一个街口,负责实现模型,控制器表示逻辑代码,由c的事情。Spring框架的功能可以用在任何J2EE服务器当中,大多数功能也适用于不受管理的环境。Spring的核心要点就是支持不绑定到特定J2EE服务的可重用业务和数据的访问的对象,毫无疑问这样的对象可以在不同的J2EE环境,独立应用程序和测试环境之间重用。

Sping三大核心思想

  • DI(依赖注入) :后台需要对象时,spring容器将给后台空对象以bean的方 式注入对象
  • IOC(控制反转) :后台对象由主动创建变被动接受,权限发生了转移
  • AOP(面向切面编程):在整个系统中,动态横向添加新的功能,还不改变原来业务流程的编码。 那么横向扩展怎么理解呢,我们在WEB项目开发中,通常都遵守三层原则:
    包括控制层(Controller)->业务层(Service)->数据层(dao),那么从这个结构下来的为纵向,它具体的某一层就是我们所说的横向。(AOP是OOP的补充)

IOC创建对象

创建Spring的xml配置applicationContext.xml
可以参考官方文档Sping官方文档

<?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="..." class="...">  
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <bean id="..." class="...">
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions go here -->
</beans>

Hello.java

package com.zx.hello;

/**
 * @Author Tim
 * @Date 2020/7/22 22:43
 * @Version 1.0
 */
public class Hello {
    private String hello;


    public String getHello() {
        return hello;
    }
     //set方法在这里是什么关键的(由set方法来注入对象的),没有Set方法就会报错 
    public void setHello(String hello) {
        this.hello = hello;
    }

    @Override
    public String toString() {
        return "Hello{" +
                "hello='" + hello + '\'' +
                '}';
    }
}

以前创建对象:

Hello hello = new Hello();

现在在Sping配置文件中(前提是要保证Hello这个类必须存在):
id = 变量名 – hello
class = new Hello();
bean = 对象
property = 对象属性值

<?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来创建对象,在Spring中统一叫做Bean-->
    <!--	该id属性是标识单个bean定义的字符串。
            该class属性定义Bean的类型,并使用完全限定的类名。
            该id属性的值是指协作对象。在此示例中未显示用于引用协作对象的XML
     -->

    <!--
        bean = 对象
        Hello hello = new Hello();

        id = 变量名
        class =  new 的对象
        property  相当于给对象中的属性设值
    -->
	    <bean id="hello" class="com.zx.hello.Hello">
	        <!--给对象属性设值-->
	        <property name="hello" value="spring"></property>
	        <!-- collaborators and configuration for this bean go here -->
	        <!--ref是引用Spring容器中创建好的对象-->
	        <!--<property name="xx" ref="conversionService"></property>-->
	    </bean>
   </beans>

然后便可以在Java实现类中调用对象(sping 容器一加载对象就创建了)

//获取Spring上下对象(获取Spring容器)
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
//到此我们的对象就在Spring中管理了,我们要使用就直接去拿就好了。
Hello hello = (Hello) ac.getBean("hello");
Hello hello = ac.getBean("hello",Hello.class);

IOC创建对象的方式

使用无参构造创建对象(默认)
使用有参构造创建对象(如下)
    <bean id="user1" class="com.zx.user.Users">
        <!--index对象属性下标  下标赋值-->
        <constructor-arg index="0" value="李四"></constructor-arg>
    </bean>
     
    <!-- 不建议使用 当有多个相同类型就went  类型-->
    <bean id="user2" class="com.zx.user.Users">
        <constructor-arg type="java.lang.String" value="王五"></constructor-arg>
    </bean>

    <!-- 直接通过参数名-->
    <bean id="user3" class="com.zx.user.Users">
        <constructor-arg name="name" value="董彬"></constructor-arg>
    </bean>

DI(依赖注入)

依赖:bean对象的创建依赖于容器
注入:bean对象中的所有属性值由容器注入
1.构造器注入(前面)

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

    <bean id="home" class="com.zx.Home">
        <property name="home" value="安徽宣城"></property>
    </bean>
    <bean id="student" class="com.zx.Student">
        <property name="name" value="黄杰"></property>
        <property name="home" ref="home"/>
        <property name="books">
          <array>
              <value>西游记</value>
              <value>水浒传</value>
              <value>三国演义</value>
              <value>红楼梦</value>
          </array>
        </property>
        <property name="hobbys">
            <list>
                <value>多人运动</value>
                <value>篮球</value>
            </list>
        </property>

        <property name="cards">
            <map>
                <entry key="身份证" value="111111111111"></entry>
                <entry key="银行卡" value="23456s"></entry>
            </map>
        </property>

        <property name="games">
            <set>
                <value>王者荣耀</value>
                <value>刺激战场</value>
            </set>
        </property>
        <property name="info">
            <props>
                <prop key="学号">16014420048</prop>
                <prop key="姓名">大黄</prop>
            </props>
        </property>
        <property name="wrok">
            <null></null>
        </property>
    </bean>
</beans>

3.其他注入

   <?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">
    <!--需要在USER类里添加无参构造器
       p命名空间对应就是set的属性注入property
    -->
    <bean id="user1" class="com.obj.User" p:name="张三" p:age="18" scope="prototype"></bean>

    <!--需要在USER类里添加有参构造器
      c命名空间对应就是构造器注入-->
    <bean id="user2" class="com.obj.User" c:name="李四" c:age="20"></bean>

    <!--p 和 c命名空间不可以直接使用,要导入XML约束-->
    <!--scope作用域,bean的作用域 默认是单例模式singleton  原型模式prototype
     其余的在Web开发使用request、session、application
     -->
</beans>
p 和 c命名空间不可以直接使用,要导入XML约束
<!--scope作用域,bean的作用域 默认是单例模式singleton  原型模式prototype
 其余的在Web开发使用request、session、application
-->

IOC的本质

IOC(控制反转),他是一中设计思想!IOC的本质就是获得依赖对象的方式反转了,使程序不要再去管理对象的创建,使得程序的耦合大大降低,可以将对象的创建交给第三方。
控制反转就是通过描述(xml配置文件、注解)通过第三方去产生或者获取到对象的方式,在Sping中IOC容器实现了控制反转,其实现的方法便是DI(依赖注入)。

补充(自动装配)

Bean的自动装配
自动装配是Spring是满足bean依赖的一种方式,Sping会在上下文中自动寻找,并自动给bean装配属 性。spring中有三种装配方式:
1.xml中显示配置
2.在java中显示配置
3.隐式的自动装配(***)

方式一:

<?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="cat" class="com.zx.Cat">
        <property name="name" value="猫因"/>
    </bean>

    <bean id="dog" class="com.zx.Dog">
        <constructor-arg name="name" value="豆豆"/>
    </bean>

    <bean id="people" class="com.zx.People">
        <property name="name" value="大黄"/>
        <property name="cat" ref="cat"/>
        <property name="dog" ref="dog"/>
    </bean>

    <!--自动装配-->
    <!-- byName 会自动在容器中寻找和自己对象set方法后面的值对应的bean  id-->
    <bean id="people1" class="com.zx.People" autowire="byName">
        <property name="name" value="亚飞"/>
    </bean>

    <!-- byType 会自动在容器中寻找和自己对象类型相同的bean  id-->
    <bean id="people2" class="com.zx.People" autowire="byType">
        <property name="name" value="董小姐"/>
    </bean>

</beans>
import com.zx.People;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @Author Tim
 * @Date 2020/7/23 17:12
 * @Version 1.0
 */
public class Test6 {
    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        People people = ac.getBean("people",People.class);
        people.getCat().show();
        people.getDog().show();
        System.out.println("这个人叫"+people.getName());


        People people1 = ac.getBean("people1",People.class);
        people1.getCat().show();
        people1.getDog().show();
        System.out.println("这个人叫"+people1.getName());


        People people2 = ac.getBean("people2",People.class);
        people2.getCat().show();
        people2.getDog().show();
        System.out.println("这个人叫"+people2.getName());


    }
}

方式二、
使用JAVA的方式来配置Spring
完全不用Spring的XML配置了
JavaConfig是Spring的一个子项目,在Spring4之后变为一个核心功能

@Configuration代表是一个配置``类,就和我们之前的bean.xml一样

@ComponentScan("com.zx")扫描包

@Bean//注册一个bean就相当于bean标签,方法名字就是id,返回值就是class属性
package com.config;

import com.zx.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @Author Tim
 * @Date 2020/7/24 17:51
 * @Version 1.0
 */
@Configuration//这个也会被容器托管,注册到容器中,因为他本就是一个@Component
@ComponentScan("com.zx")//不写也可以
public class UserConfig {
    @Bean//注册一个bean就相当于bean标签,方法名字就是id,返回值就是class属性
    public User getUser(){
        return new User();
    }
}

package com.zx;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * @Author Tim
 * @Date 2020/7/24 17:48
 * @Version 1.0
 */
@Component
public class User {
    private String name;

    public String getName() {
        return name;
    }
    @Value("张三")
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}

import com.config.UserConfig;
import com.zx.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @Author Tim
 * @Date 2020/7/24 17:57
 * @Version 1.0
 */
public class Test9 {
    public static void main(String[] args) {
        //如完全使用配置方法去做,通过 AnnotationConfigApplicationContext上下文去获取容器,通过配置类的class对象加载
        ApplicationContext ac = new AnnotationConfigApplicationContext(UserConfig.class);
        User user = ac.getBean("getUser",User.class);
        System.out.println(user.getName());
    }
}

方式三、
注解实现自动装配
使用注解要开启注解支持

 <context:annotation-config/>
1.@Autowired  直接在属性上使用即可或者在Set方法上使用也可以。 这个注解使用反射的方式实现的,可以不写   
 SET方法也是可以注入的(前提是你要自动装配的属性在IOC容器(spring)中存在 ,符合byType)如果自动装配
 的环境比较复杂,可以添加@Qualifier(value = "dog111")去配合@Autowired,获取唯一值。@Autowired(required = 
 false)//required = false 允许在容器中为null
  
2.@Resource (是JDK的注解。不是Sping)
      
3.@Nullable
如果可以传入NULL值,则标记为@Nullable,如果不可以,则标注为@Nonnull。那么在我们做一些不安全严谨操作
的编码操作时,这些注释会给我们一些警告。


@Resource和@Autowired都是做bean的注入时使用,其实@Resource并不是Spring的注解,它的包是
javax.annotation.Resource,但是Spring支持该注解的注入。

1、共同点
两者都可以写在字段和setter方法上。两者如果都写在字段上,那么就不需要再写setter方法。

2、不同点
(1)@Autowired
    @Autowired为Spring提供的注解,需要导入包org.springframework.beans.factory.annotation.Autowired;只按照
    byType注入。@Autowired注解是按照类型(byType)装配依赖对象,默认情况下它要求依赖对象必须存在,如果
    允许null值,可以设置它的required属性为false.如果我们想使用按照名称(byName)来装配,可以结合@Qualifier
    注解一起使用。

(2)@Resource
    @Resource默认按照ByName自动注入,由J2EE提供,需要导入包javax.annotation.Resource。@Resource有两
    个重要的属性:name和type,而Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析bean
    的类型。所以,如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策
    略。如果既不制定name也不制定type属性,这时将通过反射机制使用byName自动注入策略。

Spring注解开发
在spring4之后要使用注解开发,必须保证导入aop架包
1.使用注解要增加注解支持!(主要是开启程序的注解驱动)

  <context:annotation-config/>
2.扫描机制
指定要扫描的包,这个包下的注解就会生效(Spring特定的注解)
<context:component-scan base-package="com"/>
注解(bean)
1.@Component(组件)
    @Component 
    等价与 
    <bean id="user" class="com.entity.User"></bean>
2.@Value()
    Spring注解注入属性值使用 @Value("大黄")
    相当于
    <property name="xxx" value="xxx"></property>
3.@Component的衍生注解
  (1)@Repository(仓库 持久层)
  (2)@Service(业务层)
  (3)@Controller(控制层)
   这四个注解的功能都是一样的,都是代表将某个类注册到Spring中,装配Bean
4.作用域的注解
    @Scope("singleton")
package com.bean;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;

import javax.annotation.Resource;

/**
 * @Author Tim
 * @Date 2020/7/24 14:37
 * @Version 1.0
 */
public class Peope {
    @Resource
    private Cat cat;
    @Autowired(required = false)//required = false 允许在容器中为null
    @Qualifier(value = "dog111")
    private Dog dog;

    private String name;

    public void show(){
        cat.Show();
        dog.show();
        System.out.println("你们都是我的宠物");
    }
}
package com.bean;

/**
 * @Author Tim
 * @Date 2020/7/24 14:30
 * @Version 1.0
 */
public class Cat {
    private String name;
    public void Show(){
        System.out.println("你好我是小猫咪");
    }
}



package com.bean;

/**
 * @Author Tim
 * @Date 2020/7/24 14:36
 * @Version 1.0
 */
public class Dog {
    private String name;
    public void show(){
        System.out.println("我是一个汪星人");
    }
}


<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://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="com.bean.Cat"></bean>
    <bean id="dog11" class="com.bean.Dog"></bean>
    <bean id="dog111" class="com.bean.Dog"></bean>

    <bean id="people" class="com.bean.Peope"></bean>
    <!-- 开启注解支持-->
    <context:annotation-config/>

</beans>

本文地址:https://blog.csdn.net/weixin_43963801/article/details/107594322

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网