Spring IOC

◆ 传统Javaweb开发的困惑

◆ IoC、DI和AOP思想提出

◆ Spring框架的诞生

Spring | Home

IOC控制反转:BeanFactory 快速入门

java 复制代码
package com.xiaolin.service.Impl;

import com.xiaolin.dao.UserDao;
import com.xiaolin.service.UserService;

public class UserServiceImpl implements UserService {
    //该方法是BeanFactory去调用该方法  从容器中获取userDap设置到此处
    public void setUserDao(UserDao userDao) {
        System.out.println("该方法是BeanFactory去调用该方法  从容器中获取userDap设置到此处"+userDao);
    }
}
java 复制代码
package com.xiaolin.service;

public interface UserService {
}
java 复制代码
public class BeanFactoryTest {
    public static void main(String[] args) {
        //创建工厂对象
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        //创建一个读取器(xml文件)
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        //读取器配置文件给工厂
        reader.loadBeanDefinitions("beans.xml");
        //根据id获取Bean实例对象

        UserService userService = (UserService) beanFactory.getBean("userService");
//        System.out.println(userService);
    }
}

DI依赖注入:BeanFactory 快速进阶(在一个bean对象中嵌套另一个bean对象)

java 复制代码
package com.xiaolin.dao.Impl;

import com.xiaolin.dao.UserDao;

public class UserDaoImpl implements UserDao {
}
java 复制代码
package com.xiaolin.dao;

public interface UserDao {
}
java 复制代码
public class BeanFactoryTest {
    public static void main(String[] args) {
        //创建工厂对象
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        //创建一个读取器(xml文件)
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        //读取器配置文件给工厂
        reader.loadBeanDefinitions("beans.xml");
        //根据id获取Bean实例对象
        UserService userService = (UserService) beanFactory.getBean("userService");
//        System.out.println(userService);

        UserDao userDao = (UserDao) beanFactory.getBean("userDao");
//        System.out.println(userDao);
    }
}

- ApplicationContext快速入门

java 复制代码
package com.xiaolin.test;

import com.xiaolin.service.UserService;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ApplicationContextTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService) applicationContext.getBean("userService");
        System.out.println(userService);
    }
}

applicationContext.xml

java 复制代码
<?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">
<!--    配置UserServiceImpl-->
    <bean id="userService" class="com.xiaolin.service.Impl.UserServiceImpl">
        <property name="userDao" ref="userDao"></property>
    </bean>
<!--    配置UserDao
           将userDao设置给userService
-->
    <bean id="userDao" class="com.xiaolin.dao.Impl.UserDapImpl"></bean>
</beans>

BeanFactory与ApplicationContext的关系

BeanFactory的继承体系

ApplicationContext的继承体系

◆ 基于xml的Spring应用

- SpringBean 的配置详解

1)Bean的基础配置

2)Bean的别名配置

3)Bean的范围配置 【singleton(单例模式)/prototype(多对象模式)】

4)Bean的延迟加载

5)Bean的初始化和销毁方法配置

方法一:init-method/destory-method
方法二: 实现InitializingBean

6)Bean的实例化配置【创建Bean方式】

方法一:构造方法实例化:<constructor-arg>

当没有无参构造方法而使用有参构造方法时候,要在相关的配置文件中使用<constructor-arg>,进行配置,name对应参数名,value对应相关的值

方法二:工厂方法实例化

⚫ 静态工厂方法实例化Bean
⚫ 实例工厂方法实例化Bean
⚫ 实现FactoryBean规范延迟实例化Bean

7)Bean的依赖注入配置

注入 List 集合
注入 Set 集合
注入 Map 集合
注入 Properties 键值对

扩展:自动装配方式

8)Spring的其他配置标签

<bean>标签

指定其他环境的情况下,默认环境都起作用

<import>标签
<alisas>标签:起别名
Spring的自定义标签

先在pom导入坐标

- Spring 的get方法

java 复制代码
        Object userDao1 =applicationContext.getBean("userDao1");
        UserDao userDao11 = applicationContext.getBean("userDao1", UserDao.class);
        UserDao bean = applicationContext.getBean(UserDao.class);

- Spring 配置非自定义Bean

1)配置 Druid 数据源交由Spring管理

java 复制代码
    <!-- mysql驱动 -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.49</version>
    </dependency>
    <!-- druid数据源 -->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.23</version>
    </dependency>
java 复制代码
    <!--配置 DruidDataSource数据源-->
    <bean class="com.alibaba.druid.pool.DruidDataSource">
        <!--配置必要属性-->
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc://localhost:3306/mybatis"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>

2)配置Connection交由Spring管理【静态工厂方法】

3)配置日期对象交由Spring管理 【实例化工厂方法】

4)配置MyBatis的SqlSessionFactory交由Spring管理【多种配置方法统一】

mybatis-conifg.xml

- Bean 实例化的基本流程

- Spring的后处理器

beanDefinitionMap->bean工厂后处理器->循环map(实例化->bean后处理器->填充到单例池)

BeanFactoryPostProcessor

BeanDefinition

BeanDefinitionRegistryPostProcessor[BeanFactoryPostProcessor的子接口]

小总结:

自定义注解【注解的底层实现】

BeanPostProcessor

对Bean方法进行执行时间日志增强

java 复制代码
public class TimeLogBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

        //使用动态代理对目标Bean进行增强,返回proxy对象,进而存储到单例池singletonObjects中
        Object beanProxy = Proxy.newProxyInstance(
                bean.getClass().getClassLoader(),
                bean.getClass().getInterfaces(),
                (proxy, method, args) -> {
                    //1、输出开始时间
                    System.out.println("方法:" + method.getName() + "-开始时间:" + new Date());
                    //2、执行目标方法
                    Object result = method.invoke(bean, args);
                    //3、输出结束时间
                    System.out.println("方法:" + method.getName() + "-结束时间:" + new Date());

                    return result;
                }
        );

        return beanProxy;
    }
}

- Spring Bean的生命周期

Bean初始化阶段

Bean实例属性填充
注入双向对象引用
三级缓存(解决注入双向对象引用)

P54底层源码(欠)

常用的Aware接口

- Spring IoC 整体流程总结

硬核讲解:

55-Spring IoC容器实例化Bean整体流程图_哔哩哔哩_bilibili

- Spring xml方式整合MyBatis

Spring整合MyBatis --纯手写Mybatis整合

java 复制代码
public interface UserMapper {

    List<User> findAll();

}
XML 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.UserMapper">
    <select id="findAll" resultType="com.itheima.pojo.User">
        select * from tb_user
    </select>
</mapper>
复制代码
mybatis-config.xml
XML 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <package name="com.itheima.mapper"></package>
    </mappers>

    
</configuration>
复制代码
MyBatisTest
java 复制代码
public class MyBatisTest {

    public static void main(String[] args) throws Exception {

        InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = builder.build(in);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> all = mapper.findAll();
        for (User user : all) {
            System.out.println(user);
        }

    }

}

Spring整合MyBatis

java 复制代码
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.13.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.5</version>
        </dependency>
java 复制代码
    <!--配置数据源信息-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

    <!--配置SqlSessionFactoryBean,作用将SqlSessionFactory存储到spring容器-->
    <bean class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--MapperScannerConfigurer,作用扫描指定的包,产生Mapper对象存储到Spring容器-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.itheima.mapper"></property>
    </bean>

Spring整合MyBatis的原理剖析

SqlSessionFactoryBean

执行完SqlSessionFactoryBean后,里面调用了getObject然后产生SqlSessionFactory。

MapperScannerConfigurer

60-Spring整合第三方框架-MyBatis整合Spring-MapperScannerConfigurer_哔哩哔哩_bilibili

Spring xml方式整和第三方框架【自定义命名空间】

使用外部配置文件

javascript 复制代码
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=root
java 复制代码
    <!--加载properties文件-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!--配置数据源信息-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>
硬核讲解

62-Spring整合第三方框架-自定义命名空间解析原理_哔哩哔哩_bilibili

基本流程

P-65-66

◆ 基于注解的Spring应用

- Bean基本注解开发

在@Component后面不加value值,默认id是该类名首字母小写

- Bean依赖注入注解开发

@Value

@Autowired【根据类型进行注入】

根据类型进行注入,如果同一个类型的Bean有多个,尝试根据名字进行二次匹配,匹配变不成功的则匹配失败

@Qualifier

结合@Autowired一起使用,作用是根据名称注入相应的Bean

在非自定义属性上要@Autowird+@Qualifier

在自定义属性中添加参数名可以单独使用@Qualifier

@Resource

不指定名称参数时,根据类型注入【@Autowired】,指定名称就根据名称注入【@Autowired+@Qualifier】

- 非自定义Bean注解开发【@Bean】

注意点:

java 复制代码
@Component
public class OtherBean {

    @Bean("dataSource")
    public DataSource dataSource(
            @Value("${jdbc.driver}") String driverClassName,
            @Qualifier("userDao2") UserDao userDao,
            UserService userService
    )
    {

        /*System.out.println(driverClassName);
        System.out.println(userDao);
        System.out.println(userService);*/


        DruidDataSource dataSource = new DruidDataSource();
        //设置4个基本参数 ...

        return dataSource;
    }

}

- Bean配置类的注解开发【替代整个配置文件】

@Configuration

@ComponentScan

@PropertySource

@Import

java 复制代码
@Configuration  //标注当前类是一个配置类(替代配置文件)+@Component-->替代了<bean>

//<context:component-scan base-package="com.itheima"/>
@ComponentScan("com.itheima")//相当于包扫描

//<context:property-placeholder location="classpath:jdbc.properties"/>
@PropertySource("classpath:jdbc.properties")//属性资源

//<import resource=""></import>
@Import(OtherBean.class)

- Spring 配置其他注解

@Primary

@Profile 【切换环境】

没有指定环境,在任何情况下都可以使用

- Spring注解的解析原理

- Spring注解方式整合第三方框架

使用xml

使用注解

@import

@Import导入实现了ImportSelector接口的类

@Import导入实现ImportBeanDefinitionRegistrar接口
相关推荐
Vic101015 分钟前
Java 开发笔记:多线程查询逻辑的抽象与优化
java·服务器·笔记
Biaobiaone6 分钟前
Java中的生产消费模型解析
java·开发语言
特立独行的猫a31 分钟前
11款常用C++在线编译与运行平台推荐与对比
java·开发语言·c++
louisgeek41 分钟前
Java 位运算
java
hweiyu001 小时前
Maven 私库
java·maven
Boilermaker19921 小时前
【Java EE】SpringIoC
前端·数据库·spring
Super Rookie2 小时前
Spring Boot 企业项目技术选型
java·spring boot·后端
写不出来就跑路2 小时前
Spring Security架构与实战全解析
java·spring·架构
ZeroNews内网穿透2 小时前
服装零售企业跨区域运营难题破解方案
java·大数据·运维·服务器·数据库·tcp/ip·零售
sleepcattt3 小时前
Spring中Bean的实例化(xml)
xml·java·spring