Spring入门之IOC详解

众所周知,Spring 是目前市面上最主流的一款功能非常强大的框架,中文意思是春天,也让我们开发人员从JSP、sevlet的高耦合的开发中彻底的解救出来。废话少说,接下来就进行详细介绍。

【1】Spring是什么

Spring是一个开源框架,Spring的核心是控制反转(IOC)和面向切面(AOP)。

简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架。

轻量级:与EJB对比,依赖资源少,销毁的资源少。
分层: 一站式,每一个层都提供的解决方案

  • web层:struts2,spring-MVC
  • service层:spring
  • dao层:hibernate,mybatis , jdbcTemplate --> spring-data

【2】Spring优势

Spring 出现是为了解决JavaEE 实际问题:

  • 方便解耦,简化开发 (IOC)

    Spring就是一个大工厂(容器),可以将所有对象创建和依赖关系维护,交给Spring管理

    Spring工厂是用于生成bean

  • AOP编程的支持

    ​ Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能

  • 声明式事务的支持

    ​ 只需要通过配置就可以完成对事务的管理,而无需手动编程

  • 方便程序的测试

    ​ Spring对Junit4支持,可以通过注解方便的测试Spring程序

  • 方便集成各种优秀框架

    ​ Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz等)的直接支持

  • 降低JavaEE API的使用难度

    ​ Spring 对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低

基于这些特性,我们也会俗称Spring为开发架构的粘合剂

【3】Spring体系结构

可以访问官网进行自主学习:https://spring.io/

Spring框架至今已集成了20多个模块,这些模块分布在以下模块中:

核心容器(Core Container)
数据访问/集成(Data Access/Integration)层
Web层
AOP(Aspect Oriented Programming)模块
植入(Instrumentation)模块
消息传输(Messaging)
测试(Test)模块

Spring入门之IOC详解_第1张图片

【4】Spring核心

  • 控制反转(Inversion of Control,IOC
  • 面向切面编程(aspect-oriented programming,AOP

Spring所有功能都依赖于这两个核心

注意:IOC和AOP并不是一种技术,而是一种思想,这点要清楚。

接下来就来讲一下IOC

【5】IOC

IOC介绍:IOC 全称为 Inversion of Control,翻译为 “控制反转”。

控制:控制对象的创建与销毁

反转:将对象的控制权(创建与销毁)交给Spring的IOC容器。

作用:解耦。

由于Java是面向对象开发,开发过程中由N个对象构成,各对象互相合作完成需求。但是此过程存在一个很大的问题,就是各个对象间耦合度太高,导致后期维护困难。

而Spring提供了一种IOC思想,就是引用“第三方”:IOC容器实现具有依赖关系的对象之间的解耦。全部对象的控制权都交给IOC容器,包括创建、销毁,这样各对象间就解除了关系,独立存在。

其他解释:

什么是ioc:控制反转,以前我们要获取对象,我们自己new.主动获取。现在有了工厂模式,我们需要获取对象,是工厂创建,我们被动接受工厂创建的对象.这就是控制反转.说白了ioc就是工厂模式. 

Spring入门之IOC详解_第2张图片

spring框架提供了一个大工厂接口:ApplicationContext(父接口Beanfactroy)

spring-IOC的配置采取的是什么类型?

spring使用XML格式的文件存储配置
	<bean id="唯一标识" 
          class="实现类的全限定名">
	bean>

spring-IOC是怎么加载配置文件的呢?

ApplicationContext工厂使用ClassPathXmlApplicationContext加载配置文件

基于多个实现类需要进行功能切换,我们只需要修改配置文件,不需要改java代码,所以不需要重新编译。

【6】IOC的XML开发

使用一个入门小案例来讲解

使用ApplicationContext:spring-IOC容器创建对象

1.配置pom.xml,引入spring-context依赖


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0modelVersion>

  <groupId>com.vv.springgroupId>
  <artifactId>spring-iocartifactId>
  <version>1.0-SNAPSHOTversion>

  <name>spring-iocname>
  
  <url>http://www.example.comurl>
    
  <properties>
    <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
    
    <spring.version>5.1.11.RELEASEspring.version>
  properties>

  <dependencies>
      
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-contextartifactId>
            <version>5.0.6.RELEASEversion>
        dependency>
       
        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <version>4.12version>
        dependency>
  dependencies>
  <build>
        <plugins>
            
            <plugin>
                <groupId>org.apache.maven.pluginsgroupId>
                <artifactId>maven-compiler-pluginartifactId>
                <version>3.2version>
                <configuration>
                    <source>1.8source>
                    <target>1.8target>
                configuration>
            plugin>

        plugins>
    build>
project>

2.编写配置文件applicationContext.xml


<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="accountDao" class="com.vv.spring.dao.Impl.AccountDaoImpl"/>
<bean id="accountService" class="com.vv.spring.service.Impl.AccountServiceImpl"/>
beans>

3.通过spring的工厂获取对象

public class SpringTest {
    public static void main(String[] args) {
        //1.创建spring的工厂
        ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        //2.通过spring的工厂获取对象
        Object userService = ac.getBean("userService");
        System.out.println(userService);
    }
}

bean标签详解


<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="userService" scope="prototype" init-method="init" destroy-method="destroy" class="com.itheima.service.impl.UserServiceImpl">bean>
beans>

UserServiceImpl

Spring入门之IOC详解_第3张图片

Test

public class SpringTest {
    public static void main(String[] args) {
        System.out.println("************工厂初始化start***********");
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        System.out.println("************工厂初始化end*************");
        //通过spring的工厂获取对象
        Object userService = ac.getBean("userService");
        Object userService2 = ac.getBean("userService");
        System.out.println(userService);
        System.out.println(userService2);
        //销毁工厂
        System.out.println("*************销毁工厂*****************");
        ac.close();
    }
}

运行结果

Spring入门之IOC详解_第4张图片

创建对象的4种方式


<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="userService" class="com.vv.service.impl.UserServiceImpl">bean>

    
    <bean id="userService2" class="com.vv.utils.BeanFactory" factory-method="getUserService">bean>

    
    <bean id="factoryBean2" class="com.vv.utils.BeanFactory2">bean>
    <bean id="userService3" factory-bean="factoryBean2" factory-method="getUserService" >bean>
beans>
public class UserServiceImpl implements UserService {
    //无参构造
    public UserServiceImpl() {
        System.out.println("UserServiceImpl的无参构造被调用了");
    }
}
public class BeanFactory {
	//工厂类的静态方法
    public static UserService getUserService(){
        System.out.println("工厂类的静态方法");
        return new UserServiceImpl();
    }
}
public class BeanFactory2 {
	//工厂类的动态方法
    public  UserService getUserService(){
        System.out.println("工厂类的动态方法");
        return new UserServiceImpl();
    }
}

【7】spring的依赖注入DI

Dependency Injection (依赖注入):

spring创建对象的时候,给对象的属性赋值,就是依赖注入。

注意是spring创建对象!!!

方式一:有参构造

applicationContext.xml

    
    <bean id="userService" class="com.vv.service.impl.UserServiceImpl">
        
        <constructor-arg name="age" value="23"  >constructor-arg>
        <constructor-arg name="game" value="LOL">constructor-arg>
        <constructor-arg name="username" value="张三">constructor-arg>
        <constructor-arg name="userDao" ref="userDao">constructor-arg>
    bean>

    
    <bean id="userService2" class="com.vv.service.impl.UserServiceImpl">
        <constructor-arg index="1" value="23"  >constructor-arg>
        <constructor-arg index="2" value="LOL">constructor-arg>
        <constructor-arg index="0" value="张四">constructor-arg>
        <constructor-arg index="3" ref="userDao">constructor-arg>
    bean>

    
    <bean id="userService3" class="com.vv.service.impl.UserServiceImpl">
        <constructor-arg type="java.lang.Integer" value="23"  >constructor-arg>
        <constructor-arg type="java.lang.String" value="王五">constructor-arg>
        <constructor-arg type="java.lang.String" value="LOL">constructor-arg>
        <constructor-arg type="com.vv.dao.UserDao" ref="userDao">constructor-arg>
    bean>

UserServiceImpl

public class UserServiceImpl implements UserService {
    private String username;
    private Integer age;
    private String game;
    private UserDao userDao;
    //有参构造
    public UserServiceImpl(String username, Integer age, String game, UserDao userDao) {
        this.username = username;
        this.age = age;
        this.game = game;
        this.userDao = userDao;
    }
    public UserServiceImpl() {
    }
    @Override
    public void login() {
        userDao.findUserByUser();
    }
}

Test

public class SpringTest {
    //这是一个servlet
    public static void main(String[] args) {
        //调用service的方法
        ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserService userService = (UserService)ac.getBean("userService");
        userService.login();
    }
}

方式二:set方法

applicationContext.xml

 <!-- 属性的set方法 -->
<bean id="userService" class="com.vv.service.impl.UserServiceImpl">
    <!--
        name:用来确定属性的。
            name属性的值是set的方法名去掉set后的驼峰命名名字。
        value:基本类型的属性赋值
        ref:引用型类型的属性赋值
    -->
    <property name="username" value="赵六"></property>
    <property name="age" value="25"></property>
    <property name="game" value="王者荣耀"></property>
    <property name="userDao" ref="userDao"></property>
</bean>

UserServiceImpl

public class UserServiceImpl implements UserService {
    private String username;
    private Integer age;
    private String game;
    private UserDao userDao;
    public UserServiceImpl(String username, Integer age, String game, UserDao userDao) {
        this.username = username;
        this.age = age;
        this.game = game;
        this.userDao = userDao;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public void setGame(String game) {
        this.game = game;
    }
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    public UserServiceImpl() {
    }
    @Override
    public void login() {
        userDao.findUserByUser();
    }
}

Test

public class SpringTest {
    //这是一个servlet
    public static void main(String[] args) {
        //调用service的方法
        ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserService userService = (UserService)ac.getBean("userService");
        userService.login();
    }
}

使用名称空间简写依赖注入

Spring入门之IOC详解_第5张图片

注入复杂类型的依赖

UserServiceImpl

public class UserServiceImpl2 implements UserService {
    private String[] gameNames;
    private List<String> dogType;
    private Set<String> catType;
    private Map<String,String> map;
    public void setGameNames(String[] gameNames) {
        this.gameNames = gameNames;
    }
    public void setDogType(List<String> dogType) {
        this.dogType = dogType;
    }
    public void setCatType(Set<String> catType) {
        this.catType = catType;
    }
    public void setMap(Map<String, String> map) {
        this.map = map;
    }
    @Override
    public void login(){
    }
}

applicationContext.xml


<bean id="userService" class="com.vv.service.impl.UserServiceImpl2">
    <property name="gameNames">
        <array>
            <value>LOLvalue>
            <value>PUBGvalue>
            <value>王者荣耀value>
        array>
    property>
    <property name="dogType">
        <list>
            <value>博美value>
            <value>柴犬value>
            <value>哈士奇value>
        list>
    property>
    <property name="catType">
        <set>
            <value>英短value>
            <value>橘猫value>
            <value>无毛猫value>
        set>
    property>
    <property name="map">
       <map>
           <entry value="科比" key="name">entry>
       map>
    bean>

【8】JdbcTemplate

Spring提供的JdbcTemplatemybatis框架一样,都是对jdbc的封装,用于支撑持久层的操作,但企业开发中mybatis应用较广。

下面就对JdbcTemplate的用法进行简单介绍。

步骤:

1、搭建数据库环境;
2、创建工程导入依赖

<dependencies>
    
    <dependency>
        <groupId>org.springframeworkgroupId>
        <artifactId>spring-jdbcartifactId>
        <version>5.0.6.RELEASEversion>
    dependency>
    
    <dependency>
        <groupId>junitgroupId>
        <artifactId>junitartifactId>
        <version>4.12version>
    dependency>
    
    <dependency>
        <groupId>org.springframeworkgroupId>
        <artifactId>spring-contextartifactId>
        <version>5.0.6.RELEASEversion>
    dependency>
    
    <dependency>
        <groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
        <version>5.1.38version>
    dependency>
dependencies>

3、创建pojo层
4、实现dao层接口和实现类
5、实现service层接口和实现类
6、通过配置文件实现IOC和依赖注入

<?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">

    <!--accountService-->
    <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
        <!--注入accountDao-->
        <property name="accountDao" ref="accountDao"></property>
    </bean>

    <!--accountDao-->
    <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
        <!--依赖注入jdbcTemplate-->
        <property name="jdbcTemplate" ref="jdbcTemplate"></property>
    </bean>

    <!--jdbcTemplate对象-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!--依赖注入数据源-->
        <constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
    </bean>

    <!--创建数据源对象-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <!-- set方法依赖注入-->
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/itheima115_spring_day02"></property>
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
    </bean>
</beans>

7、创建测试用例完成测试
8、优化-加载外部数据源

pom.xml


<dependency>
    <groupId>com.alibabagroupId>
    <artifactId>druidartifactId>
    <version>1.0.9version>
dependency>

<dependency>
    <groupId>c3p0groupId>
    <artifactId>c3p0artifactId>
    <version>0.9.1.2version>
dependency>

<dependency>
    <groupId>commons-dbcpgroupId>
    <artifactId>commons-dbcpartifactId>
    <version>1.4version>
dependency>

applicationContext.xml


<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    
    <property name="username" value="${jdbc.username}">property>
    <property name="password" value="${jdbc.password}">property>
    <property name="url" value="${jdbc.url}">property>
    <property name="driverClassName" value="${jdbc.driverClass}">property>
bean>


    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        
        <property name="user" value="${jdbc.username}">property>
        <property name="password" value="${jdbc.password}">property>
        <property name="jdbcUrl" value="${jdbc.url}">property>
        <property name="driverClass" value="${jdbc.driverClass}">property>
    bean>


<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    
    <property name="username" value="${jdbc.username}">property>
    <property name="password" value="${jdbc.password}">property>
    <property name="url" value="${jdbc.url}">property>
    <property name="driverClassName" value="${jdbc.driverClass}">property>
bean>

【9】IOC的注解开发

注解开发的优点:提高开发效率。

主要分为下面几个类型使用:

创建对象:@component; @Controller; @Service; @Repository;
依赖注入:@Autowired; @Qualifier; @Resource(name=beanid); @Value;
生命周期:@Scope; @PostConstruct; @PreDestroy;
纯注解开发相关:@Configuration; @ComponentScan; @PropertySource; @Import; @Bean
Spring整合单元测试:@RunWith; @ContextConfiguration;

具体的使用方法还没来得及总结,有空发出来。

你可能感兴趣的:(Spring,spring,ioc)