java Sping IOC总结于B站尚硅谷

github对应源码
B站视频

什么是框架?

高度抽取可重用代码的一种设计,高度的通用性

什么是spring?

容器框架,把组件(类)管理起来

spring 学好2个:

IOCAOP

在这里插入图片描述

在这里插入图片描述

IOC: 控制反转 ---> 资源的获取方式
 |--- 主动式: 自己new对象
 |--- 被动式: 让容器来new对象并赋值
spring框架
Test(绿色)   :spring的单元测试模块

Core Container:核心容器(IOC)黑色代表这部分由哪些jar包组成,要使用这个部分的完整功能,要导入jar包

	spring-core:提供了框架的基本组成部分,包括 IoC 和依赖注入功能。
	spring-beans:提供 BeanFactory,
	spring-context:模块建立在由core和 beans 模块的基础上建立起来的,它以一种类似于JNDI注册的方式访问对象。	 Context模块继承自Bean模块,并且添加了国际化(比如,使用资源束)、事件传播、资源加载和透明地创建上下文(比	如,通过Servelet容器)等功能
	spring-expression:提供了强大的表达式语言,用于在运行时查询和操作对象图。它是JSP2.1规范中定义的统一表达式语言的扩展,支持set和get属性值、属性赋值、方法调用、访问数组集合及索引的内容、逻辑算术运算、命名变量、通过名字	  从Spring IoC容器检索对象,还支持列表的投影、选择以及聚合等


AOP+Aspects :面向切面编程模块

Data Access :数据访问模块

Web         :Spring开发Web引用模块
spring的Helloworld

1.框架编写流程规定:

1.导包   2.写配置   3.测试

2.spring-helloworld的依赖包

spring-core-5.2.6.RELEASE.jar
spring-context-5.2.6.RELEASE.jar
spring-expression-5.2.6.RELEASE.jar
spring-beans-5.2.6.RELEASE.jar
commons-logging-1.1.1.jar

3.spring的配置文件

idea: src 点击new ---> xml configuration File ---> spring config

在这里插入图片描述

配置文件内容:

<?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">
    <!--注册Person对象,Spring 会自动创建这个Person的对象
        一个Bean标签可以注册一个组件(对象、类)
        class: 写要这侧的组件的全类名
        id :这个对象的唯一标识  用于getBean中
    -->
    <bean id="person1" class="com.ralph.bean.Person">
        <!-- 使用property标签为Person对象的属性赋值-->
        <property name="lastName" value="ralph"></property>
        <property name="age" value="14"></property>
        <property name="gender" value="1"></property>
        <property name="email" value="ralph@eamil.com"></property>
    </bean>
</beans>

4.测试

    /**
     * Description: 从容器中获取这个组件(类)
     * return     Person{lastName='ralph', age=14, gender='1', email='ralph@eamil.com'}
     * Author:     ralph
     **/
    @Test
    public void demoTest1(){
        //ApplicationContext 表示当前容器
        ApplicationContext context = new ClassPathXmlApplicationContext("ioc.xml");
        Object person1 = context.getBean("person1");
        System.out.println(person1);
    }

在这里插入图片描述

FileSystemXmlApplicationContext: 可以让ioc配置文件放在某个磁盘路径下面
ClassPathXmlApplicationContext: ioc配置文件在类的路径下面

5.注意事项:

1. 容器中对象的创建在容器创建的时候就已经new好了
2. 同一个组件中默认是单实例 
3. property属性标签会利用setter方法为Javabean的属性进行赋值
4. javabean的属性名是由get和set方法觉得
5. 如果ioc容器中由多个类型的bean 使用类的方式查找就会报错

	//测试类
    public void demoTest2(){
    	//报错内容:
        // org.springframework.beans.factory.NoUniqueBeanDefinitionException:
        // No qualifying bean of type 'com.ralph.bean.Person'
        // available: expected single matching bean but found 2: person1,person2
        Person bean = context.getBean(Person.class);
        System.out.println(bean);
    }
    
    
    // xml文件
        <bean id="person1" class="com.ralph.bean.Person">
        <!-- 使用property标签为Person对象的属性赋值-->
        <property name="lastName" value="ralph"></property>
        <property name="age" value="14"></property>
        <property name="gender" value="1"></property>
        <property name="email" value="ralph@eamil.com"></property>
    </bean>

    <bean id="person2" class="com.ralph.bean.Person">
        <!-- 使用property标签为Person对象的属性赋值-->
        <property name="lastName" value="HM"></property>
        <property name="age" value="15"></property>
        <property name="gender" value="0"></property>
        <property name="email" value="HM@eamil.com"></property>
    </bean>
        
        
    //可以使用指定bean的id + 类配合查询
        Person person2 = context.getBean("person2", Person.class);
        System.out.println(person2);

6.可以通过构造器来创建bean


    <bean id="person3" class="com.ralph.bean.Person">
        <!-- 调用有参构造器为对象的属性赋值  可以省略name 这样就要按照构造器的顺序来赋值 可以用index来指定顺序 -->
        <constructor-arg name="lastName" value="father"></constructor-arg>
        <constructor-arg name="age" value="12"></constructor-arg>
        <constructor-arg name="email" value="father@eamil.com"></constructor-arg>
        <constructor-arg name="gender" value="1"></constructor-arg>
    </bean>
P 名称空间

作用: 防止标签重复 比如<name>标签中还有name的标签

   xmlns:p="http://www.springframework.org/schema/p"
	<bean id="person4" class="com.ralph.bean.Person"
          p:age="18" p:email="chaoren@email.com" p:gender="1" p:lastName="chaoren">
    </bean>
property 引用null值的方式
    <bean id="person1" class="com.ralph.bean.Person">
        <property name="email">
            <!--进行复杂的赋值-->
            <null/>
        </property>
    </bean>

错误方式注意,使用value="null"是不对的:

<bean id="student01" class="com.xiao.bean.Student">
        <property name="name" value="null"/>
  </bean>
ref 引用外部的bean
    <bean id="person1" class="com.ralph.bean.Person">
        <!--ref 引用外部的属性-->
        <property name="car" ref="car1"></property>
    </bean>


    <bean id="car1" class="com.ralph.bean.Car">
        <property name="carName" value="c200l"></property>
        <property name="color" value="black"></property>
        <property name="price" value="270000"></property>
    </bean>

spring为list属性赋值(中间使用ref 引用外部bean)

内部bean不能再外面获取到

    <bean id="person2" class="com.ralph.bean.Person">
        <!--给list赋值-->
        <property name="books">
            <list>
                <bean id="bookin" class="com.ralph.bean.Book" p:bookName="母猪的产后护理" p:author="母猪饲养员"></bean>
                <!--通过ref 引用外部的一个元素-->
                <ref bean="bookout"/>
            </list>
        </property>
    </bean>


    <bean id="bookout" class="com.ralph.bean.Book">
        <property name="bookName" value="生发"></property>
        <property name="author" value="程序员"></property>
    </bean>
Spring 为array数组赋值
<property name="books">
    <array>
        <value>西游记</value>
        <value>红楼梦</value>
        <value>水浒传</value>
    </array>
</property>

Spring 为map赋值
        <!--给map赋值-->
        <property name="maps">
            <map>
                <entry key="k1" value="ak47"></entry>
                <entry key="k2" value="m4a1"></entry>
                <entry key="k3" value-ref="bookout"></entry>
                <entry key="k4">
                    <bean class="com.ralph.bean.Car">
                        <property name="carName" value="H"></property>
                    </bean>
                </entry>

            </map>
        </property>
Spring 为props赋值
<property name="info">
     <props>
         <prop key="学号">20190604</prop>
         <prop key="性别"></prop>
         <prop key="姓名">小明</prop>
     </props>
 </property>

Spring设置util名称空间

可以创建集合类型的bean 然后被其他的引用


xmlns:util="http://www.springframework.org/schema/util"
 
xsi:schemaLocation= "http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.1.xsd"
<!--util名称空间 提取出通用的集合-->

    <util:list id="myList">
        <value>玩游戏</value>
        <value>看电影</value>
    </util:list>
<!--使用ref直接引用util提取出来的集合id即可-->
    <bean id="student05" class="com.xiao.bean.Student">
        <property name="hobbys" ref="myList"/>
    </bean>

spring配置级联属性

级联属性:属性的属性 可以修改属性的属性值 不过修改后 原来的值也会修改

<bean id="person4" class="com.ralph.bean.Person">
    <property name="car" ref="car1"></property>
    <property name="car.price" value="1"></property>
</bean>
继承实现配置信息重用
  • 指定parent属性为要重用的bean的id值,不写的属性就沿用,也可以重写定义属性
  • 还可以指定属性abstract=“true”,这样的bean只能被用来继承信息,不能获取实例。否则会报异常 BeanIsAbstractException
    <bean id="person5" class="com.ralph.bean.Person" abstract="true">
        <property name="lastName" value="ralph"></property>
        <property name="age" value="14"></property>
        <property name="gender" value="1"></property>
        <property name="email" value="ralph@eamil.com"></property>
    </bean>
    <bean id="person6" class="com.ralph.bean.Person" parent="person5">
        <property name="lastName" value="ralph2"></property>
    </bean>

bean之间依赖
  1. 改变bean的创建顺序 (了解 无使用场景)

<bean id="student" class="com.xiao.bean.Student"></bean>
<bean id="address" class="com.xiao.bean.Address"></bean>
<bean id="person" class="com.xiao.bean.Person"></bean>

Student创建了
Address创建了
Person创建了

可以用depends-on属性进行设置:

<bean id="student" class="com.xiao.bean.Student" depends-on="person,address"></bean>
<bean id="address" class="com.xiao.bean.Address"></bean>
<bean id="person" class="com.xiao.bean.Person"></bean>
Person创建了
Address创建了
Student创建了
bean的作用域scope(*)

指bean是否是单实例 bean默认是单实例

  • singleton: 单例模式,是默认模式。在容器启动完成之前就已经创建好对象保存在容器中了。

  • prototype :多实例,原型模式,容器启动会不去创建,每次从容器中get的时候才会产生一个新对象

  • request:在web环境下,同一次请求创建一个bean实例(没用)

  • session:在web环境下,同一次会话创建一个bean实例(没用

静态工厂与实例工厂
  • 工厂模式:工厂帮我们创建对象;有一个专门帮我们创建对象的类,这个类就是工厂

  • 静态工厂:工厂本身不用创建对象,通过静态方法调用,对象 = 工厂类.工厂方法名( )

    class :指定静态工厂全类名

    factory-method :指定工厂方法

    constructor-arg :可以给方法传递参数

    /**
     * Description:静态工厂
     * Class:
     * Author:     ralph
     **/
    public class AirPlaneStaticFactory {
        // AirPlaneStaticFactory.getAirPlane();
        public static AirPlane getAirPlane(String jzName){
            System.out.println("静态工厂被调用");
            AirPlane airPlane = new AirPlane();
            airPlane.setFdj("1");
            airPlane.setFjsName("2");
            airPlane.setJzName(jzName);
            airPlane.setPersomNum(123);
            airPlane.setYc("3");
            return airPlane;
        }
        
        <!--bean factory for static-->
        <bean id="apstatic" class="com.ralph.factory.AirPlaneStaticFactory" factory-method="getAirPlane">
            <constructor-arg name="jzName" value="ralph"></constructor-arg>
        </bean>
    
  • 实例工厂:工厂本身需要创建对象,先创建工厂对象,再通过工厂对象创建所需对象

    ​ 工厂类 工厂对象 = new 工厂类();

        <!--bean factory for inn-->
        <bean id="apinstance" class="com.ralph.factory.AirPlaneFactory" ></bean>
        <bean id="api2" class="com.ralph.bean.AirPlane" factory-bean="apinstance" factory-method="getAirPlane">
            <constructor-arg name="jzName" value="ralph2"></constructor-arg>
        </bean>
    
    
    
        @Test
        public void factoryInstancedemo(){
            System.out.println("容器创建成功");
            Object api2 = context2.getBean("api2");
            System.out.println(api2);
    
        }
    
自定义工厂

实现了FactoryBean接口的类 是Spring可以认识的工厂类,Spring会自动调用工厂方法创建对象。

ioc容器启动的时候不会创建实例,再调用的时候才会创建实例

package com.ralph.factory;

import com.ralph.bean.Book;
import org.springframework.beans.factory.FactoryBean;

import java.util.UUID;

//自定义工厂
public class MyFactoryBean implements FactoryBean<Book> {

    /**
     * Description:判断是否是单例模式

     * return
     * Author:     ralph
     **/
    @Override
    public boolean isSingleton() {
        return false;
    }

    /**
     * Description: 返回创建的对象

     * return
     * Author:     ralph
     **/
    @Override
    public Book getObject() throws Exception {
        System.out.println("FactoryBean auto create Object");
        Book book = new Book();
        book.setBookName(UUID.randomUUID().toString());
        return book;
    }

    /**
     * Description: 返回创建的对象类型
     * Spring 会自动的调用这个方法来确定创建的对象是什么类型

     * return
     * Author:     ralph
     **/
    @Override
    public Class<?> getObjectType() {
        return Book.class;
    }
}

ioc.xml

    <bean id="myFactoryBean" class="com.ralph.factory.MyFactoryBean"></bean>
Bean的生命周期 (bean的创建到销毁)
  • 单例bean :容器启动的时候创建好,容器关闭的时候销毁
  • 多例bean:获取的时候才创建

构造器创建 ----> 初始化方法 ----> (容器执行完成关闭后)销毁方法

public class Air {
    private String name;
    private Double weight;
    private Double length;
    private Integer PersonNum;

    public void destroy(){
        System.out.println("销毁方法被调用了!");
    }

    public void init(){
        System.out.println("初始方法被调用了");
    }
}
<bean id="air04" class="com.xiao.Air" init-method="init" destroy-method="destroy"> </bean>

bean的后置处理器
  • 定义一个类实现BeanPostProcessor接口,其中两个方法postProcessBeforeInitialization和postProcessAfterInitialization会在调用初始化方法前后调用。需要注册这个实现类

  • 即使没有定义初始化方法,这两个方法也会被调用

public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("【"+beanName+"】将要调用初始化方法了..BeforeInitialization..这个bean是这样的:+【"+bean+"】");
        return bean;

    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("【"+beanName+"】初始化方法调用完了..AfterInitialization..这个bean是这样的:+【"+bean+"】");
        return bean;
    }
}


    <bean id="beanPostProcessor" class="com.ralph.bean.MyBeanPostProcessor"></bean>

spring控制数据库连接的创建

好处:用于控制连接池的创建不会调用之后创建出多个连接池

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="user" value="root"/>
        <property name="password" value="<mysql_password>"/>
        <property name="jdbcUrl" value="jdbc:mysql://<ip>:3306/<table_name>"/>
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
    </bean>
引用外包配置文件

dbconfig.properties:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=root

sql.xml:

1.需要用到context命名空间

2.使用context:property-placeholder location=" ... "标签导入数据库配置文件db.properties,就可以用$取出对应的属性了

3.Spring内部已经定义过一个username了,${username}就是系统的用户名,所以这里定义的是jdbc.username

xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd"
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="${jdbc.driver}"/>
    <property name="jdbcUrl" value="${jdbc.url}"/>
    <property name="user" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>

<context:property-placeholder location="classpath:dbconfig.properties"/>

Spring基于xml的自动装配
  • autpwire=“default/no”:不自动装配

    • <bean id="air05" class="com.xiao.Air" autowire="byName" ></bean>
      
  • autpwire=“byName”:按照名字,以属性名作为id去容器中找到这个组件,为其赋值;如果找不到就装配null

    =	car = ioc.getBean("car")
    
  • autpwire=“byType”:按照类型,以属性的类型作为查找依据去容器中找到这个组件,为其赋值,该类型必须只有一个,否则会报异常NoUniqueBeanDifinetionException;如果找不到就装配null

      =     car = ioc.getBean(Car.class) 
    

    autpwire=“construction”:按照构造器进行赋值:先按照有参构造器的参数类型进行装,如果没有就直接为组件装配null即可;如果按照类型有多个,就会把参数名作为id继续匹配,匹配到就自动装配,匹配不到就装配null。不会报错

    public Person(Car car) {
        this.car = car;
        System.out.println("Person中car的有参构造器");
    }
    <bean id="person" class="com.ralph.bean.Person" autowire="constructor"></bean>
Spring的注解开发
  1. 通过给bean上添加注解,可以快速的将bean加入到IOC容器中。创建Dao、Service、Controller层所需要用到的注解:
  • Component:组件,放在类上,将某个类注册到Spring中,id是类名首字母小写。相当于:

  • Repository:Dao持久化层

  • Servic:Service业务逻辑层

  • Controller:Controller控制器层。后面三个含义更清晰 servlet包下面的

  1. 还需要告诉Spring,自动扫描加了注解的组件:添加context名称空间 还需要有AOP包的依赖。

  2. 导入aop包

  3. 默认的组件id是类名的首字小写 通过@Repository("<set_new_name>")来设置别名

@Repository("booksql")
@Scope("prototype")
public class BookDao {
}
context:component-scan 指定扫描配置
  1. 指定要扫描的包
    <context:component-scan base-package="com.ralph">
  1. 指定组件
  • exclude-filter:排除
  • include-filter:指定哪些 只扫描进入指定的组件,默认都是全部扫描进来,use-default-filters需要设置为false:
    <context:component-scan base-package="com.ralph">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
  • type="annotation":按照注解进行排除,expression属性中指定要排除的注解的全类名

  • type="assignable":按照类名进行排除,expression属性中指定要排除的类的全类名

Spring依赖注入—Autowired 自动赋值

1.基本使用

直接在成员上添加@Autowired完成自动装配。

2.文件目录

在这里插入图片描述

//BookDao
package com.ralph.DAO;


import org.springframework.stereotype.Repository;


@Repository("booksql")
//@Scope("prototype")
public class BookDao {
    public void saveBook(){
        System.out.println("save a book");
    }
}



//BookService  使用注解@Autowired完成成员BookDao的自动装配,调用dao层的方法
package com.ralph.service;

import com.ralph.DAO.BookDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class BookService {
    @Autowired
    private BookDao bookDao;

    public void save(){
        System.out.println("<bookService> saving book!");
        this.bookDao.saveBook();
    }
}


//BookServlet  使用注解@Autowired完成成员BookService的自动装配,调用service层的方法
package com.ralph.servlet;

import com.ralph.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class BookServlet {
    @Autowired
    private BookService bookService;

    public void doGet(){
        this.bookService.save();
    }
}

3.Autowired的原理

在这里插入图片描述

4.指定注解的id

结合注解@Qualifer,指定一个id:在自动按照类型注入的基础之上,再按照指定的bean的id去查找。它在给字段注入时不能独立使用,必须和@Autowired一起使用;但是给方法参数注入时,可以独立使用。

5.方法上设置Autowired 那么每一个方法参数都是可以自动注入

@Service
public class BookService {
    private BookDao bookDao;
    @Autowired
    private void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
    public void read() {
        this.bookDao.readBook();
    }
}

6.Autowired 和Resource的区别

1. Rescource 是java的标准,扩展性强 
2. Autowired 是spring的自己
Spring 单元测试

1.导入spring的包

spring-test-5.2.6.RELEASE.jar

2.写配置

  • @ContextConfiguration:指定Spring配置文件的位置
  • @RunWith:指定用哪种驱动进行单元测试,默认是junit,这里指定用Spring的单元测试模块来执行标了@Test注解的测试方法
@ContextConfiguration(locations = "classpath:applicationContext.xml")
@RunWith(SpringJUnit4ClassRunner.class)

3.测试

    @Autowired
    BookServlet bookServlet;

    @Test
    public void springTest(){
        System.out.println(bookServlet);
    }
}
Spring 注入配合泛型的继承

逻辑图

在这里插入图片描述

Spring的IOC总结
1. ioc是一个容器,帮助我们管理组件
2. 可以通过@Autowired 自动注入依赖
3. ioc默认创建单个实例bean
4. 其实容器就是map map中保存了我们的bean
5. 所有的组件要使用Sprin都需要加入到容器中
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值