spring二刷-----IOC

spring特性

spring优点

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

spring的组成

七大模块

拓展

在这里插入图片描述

springboot

一个快速开发的脚手架
基于springboot可以快速开发单个微服务
约定大于配置!

springcloud

基于springboot实现的

缺点

违背了原来的理念,配置十分繁琐,人称“配置地狱”

IOC(重点重点)

IOC理论推导

1.UserDao接口
2.UserDaoImpl实现类
3.UserService业务接口
4.UserServiceImpl业务实现类

在之前的业务中,用户的需求可能会影响原来的代码,我们需要根据用户的需求去修改代码,如果程序代码量十分大,修改一次的成不代价十分昂贵

我们使用一个set接口实现
下面展示一些 内联代码片

private UserDao userDao;
    //利用set动态实现值的注入
    public void setUserDao(UserDao userDao){
        this.userDao = userDao;
    }

之前,程序是主动创建对象,控制权在程序员手上
** 使用set注入后,程序不再具有主动性,而是被动的接受对象**

public static void main(String[] args) {
        //用户实际调用的是业务层,dao层他们不需要接触

        UserService userService = new UserServiceImpl();
        ((UserServiceImpl)userService).setUserDao(new UserSqlserverImpl());

        userService.getUser();
    }

仔细看这段代码,有多个impl的时候,需要调用哪个impl,只需要在set传入对应的参数就好,而不需要我们再手动创建了

这种思想从本质上解决了问题,我们的程序员不用再去管理对象的创建了。系统的耦合性大大降低,可以更加专注地在业务的实现。这是IOC的原型!

IOC使用

这个就是xml文件的配置,
bean里面的class是指定实体类
property标签就是指定类的属性,value就是赋值,配合下一张图看

<?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="hello" class="com.kuang.pojo.hello">
        <!-- collaborators and configuration for this bean go here -->
        <property name="str" value="Spring"/>
    </bean>

</beans>
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 + '\'' +
                '}';
    }
}

那要怎么用呢
容器已经帮我们创建好了
getBean即可调用

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        hello hello = (com.kuang.pojo.hello) context.getBean("hello");
        hello.toString();
        System.out.println(hello.toString());
    }
  • 通过类型 获取IOC容器中bean的实例
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        com.kuang.pojo.hello bean = context.getBean(com.kuang.pojo.hello.class);
  • PS:如果有多个该类型组件则会报错
  • 解决,getBean前一个参数可以加上id名,这样就会只返回单个且不用强转
com.kuang.pojo.hello bean = context.getBean("hello",com.kuang.pojo.hello.class);

** 复杂赋值 **!!!!!
在这里插入图片描述
book类里面有别的类,应该怎么赋值呢
这里引进ref这个标签,ref就是引用外面的一个值,相当于引用外部bean
在这里插入图片描述
那如果不用ref呢,可以这样套娃,相当于引用内部bean(但是内部bean不能被获取到,只能内部使用)-----直接在beans里面写的bean为外部的,但是bean里的内嵌bean则是外部的

    <bean id="book" class="com.kuang.pojo.book">
        <!-- collaborators and configuration for this bean go here -->
        <property name="Car">
            <bean>
                
            </bean>
        </property>
    </bean>
  • 那么如何为list,map赋值呢,property里面可以添加< list >标签,map也如下
  • 在这里插入图片描述

级联属性:属性的属性就叫级联属性

细节

一、
1.ApplicationContext(容器的接口)
在这里插入图片描述
new ClassPathXmlApplicationContext(“beans.xml”);IOC容器在类路径下;
FileSystemXmlApplicationContext(“F://beans.xml”);IOC容器在磁盘路径下;
二、
1)组件的创建工作是由容器完成的
2)容器中对象的创建是在容器创建完成前就已经创建好了(不是get的时候才创建)
3)1个bean对应一个对象,同一个组件(bean)在容器中是单实例的
4)容器中如果没有该组件,获取组件会报错
在这里插入图片描述
容器中没有hello123456这个组件,则会报错
Exception in thread “main” org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named ‘hello123456’ available
在这里插入图片描述
5)IOC容器在创建这个组件对象的时候,(property)会利用setter方法为javaBean的属性进行赋值
6)javaBean的属性名是由set方法中的实现的(所以所有的get,set方法都应该自动生成)

bean的作用域
  • prototype:多实例
    1)容器启动默认不会去创建多实例bean
    2)在获取的时候(类似getbean())创建bean
    3)每次获取都会创建一个新的对象
  • singleton:单实例(默认的)
    1)在容器启动完成之前就已经创建好对象保存在容器中
    2)任何时候获取都是获取之前创建好的那个对象
    request:在web环境,同一次请求创建一个一个bean实例(没用)
    session:在web环境下,同一次会话创建一个bean实例(没用)
    在这里插入图片描述
工厂模式
自己实现普通工厂

工厂模式:创建对象,有一个类帮你去创建对象,这个类就叫工厂
AirplaneFatory.getAirPlane(String jzName);

    静态工厂:工厂本身不用创建对象,都是通过静态方法调用,工厂类.工厂方法名();
    实例工厂:工厂本身需要调用对象:
        工厂对象.工厂方法名();
<!--这样麻烦-->
    <bean id="airplane01" class="com.kuang.pojo.AirPlane">
        <property name="jzName" value="张三"></property>
    </bean>
静态工厂(不需要创建工厂本身)
    factory-method="getAirPlane"指定哪个方法是工厂方法
    constructor-arg value可以为静态工厂传参
<bean id="airplane02" class="com.kuang.fatory.AirPlaneStaticFactory" factory-method="getAirPlane">
        <constructor-arg value="李四"></constructor-arg>
    </bean>
实例工厂
        1.先配置工厂实例
        2.用factory-bean配置我们要创建的对象用哪个工厂创建
        3.用factory-method指定使用哪个工厂方法
<bean id="airPlaneInstanceFactory" class="com.kuang.fatory.AirPlaneInstanceFactory"></bean>
    <!--factory-bean:指定当前对象创建使用哪个工厂-->
    <bean id="airplane03" class="com.kuang.pojo.AirPlane"
    factory-bean="airPlaneInstanceFactory" factory-method="getAirPlane">
        <constructor-arg value="王五"/>
    </bean>
FactoryBean
  • FactoryBean是Spring指定的一个工厂,只要实现了这个接口的实现类,Spring都认为是一个工厂
  • Spring会自动调用工厂方法创建实例
  • 工厂类的编写
/**
 * 1.编写一FactoryBean的实现类
 * 2.在spring配置文件中进行注册
 */
public class MyFactoryBeanImple implements FactoryBean<AirPlane> {

    /**
     * getObject:工厂方法
     * @return 返回创建的对象
     * @throws Exception
     */
    @Override
    public AirPlane getObject() throws Exception {
        AirPlane airPlane = new AirPlane();
        airPlane.setYc("1");
        return airPlane;
    }

    /**
     * 返回创建对象的类型
     * @return Spring会自动调用这个方法来确认创建的对象是什么类型
     */
    @Override
    public Class<?> getObjectType() {
        return AirPlane.class;
    }

    /**
     *  确认是不是单例
     *  false:不是
     *  true:是
     * @return
     */
    @Override
    public boolean isSingleton() {
        return false;
    }
}

  • 注意:FactoryBean无论是单多实例,都是在获取时才创建对象
bean的生命周期
  • IOC容器中注册的bean
    1)单例bean,容器启动的时候就会创建好,容器关闭也会销毁创建的bean
    2)多实例bean,获取的时候才创建
    bean标签里的
    destroy-method,init-method(方法不能带有参数)
    单实例容器关闭时销毁bean
    多实例容器关闭互换调用销毁方法
引用外部属性文件

数据库连接池作为单实例是最好的。(略,以后直接springboot集成)

通过注解创建controller,service,dao
某个类上添加任何一个注解都能快速将这个组件加入到IOC容器的管理中

@Controller:控制器;(推荐给控制器层(servlet包下的这些))的组件添加这个注解
@Service:业务逻辑;推荐业务逻辑层添加这个注解;Service
@Repository:给数据库层(持久化层:dao层)的组件添加这个注解
@Component,给不属于以上几层的组件添加这个注解

注解可以随便加:spring底层不会去验证你的组件师傅如你注解所说。(但是为了编码规范)

  • 使用注解将组件快速加入到容器中需要几步:
    1)给要添加的组件上标四个注解中的任何一个
    2)告诉spring自动扫描这个注解(自动扫描)
    3)获取所用的组件的id就是是类名的首字母小写
    4)一定要导入Aop包,因为他是支持注解模式
    5)使用注解加入到容器中的组件,和使用配置加入到容器中的组件行为都是默认一样的
    6)组件的作用域默认就是单例的删除线格式
    context:component-scan:自动组件扫描
    base-package="":指定扫描的基础包,会把基础包及下面的所有加了注解的类早点扫描加入IOC容器
<context:component-scan base-package=""></context:component-scan>
  • 有选择的扫描类下的包
    <context:include-filter type="" expression=""/>扫描只要哪些

<context:exclude-filter type="" expression=""/>扫描不要哪些
type=“annotation”:指定排除规则:按照注解进行排除。标注指定注解的组件不要
type=“assignable”:指定排除某个具体的类
expression="":写注解的全类名

<context:component-scan base-package="">
        <context:include-filter type="annotation" expression=""/>
        <context:exclude-filter type="" expression=""/>
    </context:component-scan>
各种注解的使用
@Respository
  • 组件名的改写
   @Respository("xxx")
@Scope
  • 多实例的修改
    @Scope(value=“prototype”)
  @Respository("xxx")
  @Scope(value="prototype")
  public class BookDao{

  }

标签方法:
context:index-filter</context:index-filter>

<context:component-scan base-package="">
        <context:include-filter type="" expression=""/>
        <context:exclude-filter type="" expression=""/>
    </context:component-scan>
DI依赖注入
  • @Autowired
    自动装配:自动为这个属性赋值(可以不用new了)
@Controller
public class BookServlet{
	@Autowired
	private BookService bookService;
}
@Qualifier

1)按照类型去容器中找到对应的组件bookService = ioc.getBean(BookService);
2)没找到就抛异常
3)找到多个?
1)按照变量名作为id继续匹配:BookService,BookServiceExt
2)没有匹配上?报错,原因是因为按照变量名作为id继续匹配的

@Qualifier:指定一个名作为id,让spring别用变量名作为id匹配(写在Autowired下面即可)

找到:装配
找不到:报错
所以我们发现Autowired是一定要装备上的。
但是可以这样

@Autowired(required=false)

找不到自动装配null

方法上有Autowired注解

在这里插入图片描述

@Resource,@Inject

@Autowired:Spring自己的注释
@Resource:java的标准
也能装配

@Resource因为他是标准的所以扩展性更强

泛型依赖注入
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值