Spring-ioc-CSDN博客

148 阅读9分钟

系列文章目录


文章目录


提示:以下是本篇文章正文内容,下面案例可供参考

一、spring的优势.

1)方便解耦,简化开发
通过Spring提供的loC容器,可以将对象间的依赖关系交由Spring进行控制,避免硬编码所造成的过度耦合。用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。
2) AOP编程的支持
通过Spring的AOP功能,方便进行面向切面编程,许多不容易用传统OOP实现的功能可以通过AOP轻松实现。
3)声明式事务的支持
可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活的进行事务管理,提高开发效率和质星。
4)方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作,而是随手可做的事情。
5)方便集成各种优秀框架
Spring对各种优秀框架(Struts、Hibernate、Hessian、Quartz等)的支持。
6)降低JavaEE API的使用难度
Spring对JavaEE API(如JDBC、JavaMail、远程调用等)进行了薄薄的封装层,使这些API的使用难度大为降低.
7) Java源码是经典学习范例
Spring的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对Java设计模式灵活运用以及对Java技术的高深造诣。它的源代码无意是Java技术的最佳实践的范例。

1.1 IOC的作用

控制反转: 从对象的创建到对象的使用再到对象的销毁全部由容器来帮我们控制,用户只需要使用即可
那么我们要先告知Spring容器哪些类需要被Spring管理创建初始化对象.因此通知分为xml配置Bean标签和Bean注解的方式通知Spring容器.

那spring要做的大体流程如下:

在这里插入图片描述

1.2 IOC完全解析

在这里插入图片描述

二、Spring的开发步骤

2.1.1

在这里插入图片描述

Core Container(核心容器) Spring 的核心容器是其他模块建立的基础,由 Beans 模块、Core核心模块、Context 上下文模块和 Expression Language 表达式语言模块组成,具体介绍如下。

Beans 模块:提供了BeanFactory,是工厂模式的经典实现,Spring 将管理对象称为 Bean。
Core 核心模块:提供了 Spring 框架的基本组成部分,包括 IoC 和 DI 功能。
Context 上下文模块:建立在核心和 Beans模块的基础之上,它是访问定义和配置任何对象的媒介。ApplicationContext 接口是上下文模块的焦点。
Expression Language 模块:是运行时查询和操作对象图的强大的表达式语言。
在这里插入图片描述

①导入Spring开发的基本包坐标

在这里插入图片描述


    <dependencies>
    <!--    导入spring坐标-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.11</version>
        </dependency>
        
        <!--        导入测试坐标-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit-dep</artifactId>
            <version>4.11</version>
        </dependency>
        <!--    测试坐标-->
  
<!--        导入mysql坐标-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.24</version>
        </dependency>
        <!--        mysql坐标end-->
<!--        导入druid连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.8</version>
        </dependency>
        <!--        导入druid连接池end-->
<!--        导入spring上下文-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.11</version>
        </dependency>
        <!--        导入spring上下文end-->
        <!--        导入spring web开发api start-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
        </dependency>
        <!--        导入spring web开发end-->
    </dependencies>

②编写Dao接口和实现类


public interface UserDao {
    public void save();
}
public class UserDaoImpl implements UserDao {
	public UserDaoImpl() {
    }
    @Override
    public void save() {
        System.out.println("save running....");
    }
}

③创建Spring核心配置文件
④在Spring配置文件中配置实现类

在这里插入图片描述

⑤使用Spring的API获得 Bean 实例

public class UserDaoTest {
    public static void main(String[] args) {
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = (UserDao)app.getBean("userDao");
        userDao.save();
    }
}

三.Spring核心配置文件

3.1.1 Bean标签范围配置

scope:指对象的作用范围,取值如下:

取值范围说明
singleton默认值,单例的
prototype多例的
requestWEB项目中,Spring创建一个Bean的对象,将对象存入到request域中
sessionWEB项目中,Spring创建一个Bean的对象,将对象存入到sessiont域中
global sessionWEB项目中,应用在Portlet环境,如果没有Portlet环境那么globalSession相当于session
<!--    id唯一标识,class全限定名 -->
<!--    反射默认通过无参构造配置,因此要保证全限定名内存在无参构造器-->
<!--    scope="singleton"默认的为单例-->
    <bean id="userDao" class="com.vector.dao.impl.UserDaoImpl" scope="singleton"/>

在这里插入图片描述
在这里插入图片描述

3.1.2 Bean标签生命周期配置

init-method:指定类中的初始化方法名称
destroy-method:指定类中销毁方法名称

java

public class UserDaoImpl implements UserDao {
    public UserDaoImpl() {
    }
    @Override
    public void save() {
        System.out.println("save running....");
    }

    public void init(){
        System.out.println("初始化方法...");
    }

    public void destory(){
        System.out.println("销毁方法...");
    }
}

xml

 <bean id="userDao" class="com.vector.dao.impl.UserDaoImpl" scope="singleton" init-method="init" destroy-method="destory"/>

test

public class UserDaoTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = (UserDao)app.getBean("userDao");
        System.out.println(userDao);
        app.close();
    }
}

3.2.1Bean实例化

//静态工厂

//User接口
public interface UserDao {
    public void save();
}
//User接口的实现
public class UserDaoImpl implements UserDao {
    public UserDaoImpl() {
        System.out.println("UserDaoImpl被创建...");
    }
    @Override
    public void save() {
        System.out.println("save running...");
    }

    public void init(){
        System.out.println("初始化方法...");
    }

    public void destory(){
        System.out.println("销毁方法...");
    }
}
//静态工厂创建user的实例化对象
public class FactoryStatic {
    public static UserDao getUserDao(){
        return new UserDaoImpl();
    }
}


<!--    Bean获取无参构造对象-->
<!--    <bean id="userDao" class="com.vector.dao.impl.UserDaoImpl" scope="singleton"/>-->
<!--    Bean获取静态工厂创建的对象-->
<bean id="userDao" class="com.vector.dao.factory.FactoryStatic" scope="singleton" factory-method="getUserDao"/>
<!--    Bean获取动态工厂创建的对象-->
<!--    <bean id="factoryStatic" class="com.vector.dao.factory.FactoryStatic" scope="singleton"/>-->
<!--    <bean id="userDao" factory-bean="factoryStatic" factory-method="getUserDao"/>-->
//测试类调用

public class UserDaoTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = (UserDao) app.getBean("userDao");
        System.out.println(userDao);
        //app.close();
    }
}

3.3依赖注入

在这里插入图片描述
在这里插入图片描述

依赖注入(Dependency Injection) :它是Spring框架核心IOC的具体实现。
在编写程序时,通过控制反转,把对象的创建交给了Spring,,但是代码中不可能出现没有依赖的情况。IOC解耦只是降低他们的依赖关系,但不会消除。例如:业务层仍会调用持久层的方法。

那这种业务层和持久层的依赖关系,在使用Spring之后,就让Spring来维护了。简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取。

3.3.1 Bean的依赖注入配置方法

set方法

在这里插入图片描述

在这里插入图片描述

其他依赖注入方式

详情此处

3.4引入其他配置文件

<import resource="文件名.xml"/> 

标签
id属性:在容器中Bean实例的唯一标识,不允许重复
class属性:要实例化的Bean的全限定名
scope属性:Bean的作用范围,常用是singleton (默认)和prototype
标签:属性注入
name属性:属性名称
value属性:注入的普通属性值ref属性:注入的对象引用值标签
标签
标签
标签
标签:导入其他的spring的分文件

3.5 springAPI

  1. ClassPathXmlApplicationContext
    它是从类的根路径下加载配置文件推荐使用这种
    2)FileSystemXmlApplicationContext
    它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。
  2. AnnotationConfigApplicationContext
    当使用注解配置容器对象时,需要使用此类来创建spring容器。它用来读取注解。

3.6 配置数据源(连接池)文件 Druid

注意:

1.applicationContext.xml 文件中name值必须与连接池方法名相同.可以使用DruidDataSource dataSource = new DruidDataSource();
dataSource .setxxxx;寻找name值.
在这里插入图片描述
在这里插入图片描述
2.
在这里插入图片描述

使用了spring,配置文件中的username不能叫username,spring会默认username是你的计算机名,解决办法,把username改个名字即可。或在每个配置信息前面加上 jdbc. 即可(jdbc.username).

applicationContext.xml

<applicationContext.xml version="1.0" encoding="UTF-8"?>
   <!-- 引入context命名空间和约束地址-->
<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 http://www.springframework.org/schema/context/spring-context.xsd">

    <!--    加载外部的properties文件-->
    <context:property-placeholder location="classpath:druid.properties"/>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="DriverClassName" value="${jdbc.driverClassName}"/>
        <property name="Url" value="${jdbc.url}"/>
        <property name="Username" value="${jdbc.username}"/>
        <property name="Password" value="${jdbc.password}"/>
        <!-- 统计监控过滤器 -->
        <property name="filters" value="stat"/>
        <!-- 连接池设置 -->
        <property name="maxActive" value="20"/>
        <property name="initialSize" value="1"/>
        <property name="maxWait" value="60000"/>
        <property name="minIdle" value="1"/>
        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="60000"/>
        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="300000"/>
        <property name="validationQuery" value="SELECT 'x'"/>
        <property name="testWhileIdle" value="true"/>
        <property name="testOnBorrow" value="false"/>
        <property name="testOnReturn" value="false"/>

        <property name="poolPreparedStatements" value="true"/>
        <property name="maxOpenPreparedStatements" value="20"/>
    </bean>
</beans>

druid.properties文件


jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
jdbc.username=root
jdbc.password=123456
filters=stat
initialSize=2
maxActive=300
maxWait=60000
timeBetweenEvictionRunsMillis=60000
minEvictableIdleTimeMillis=300000
validationQuery=SELECT 1
testWhileIdle=true
testOnBorrow=false
testOnReturn=false
poolPreparedStatements=false
maxPoolPreparedStatementPerConnectionSize=200

测试

@Test
/**
 * spring代理druid配置文件连接池
 */
public void getDruidProerties() throws Exception {
    ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
    DataSource dataSource = (DataSource) app.getBean("dataSource");
    Connection conn = dataSource.getConnection();
    System.out.println(conn);
    conn.close();
}

在这里插入图片描述

spring注解配置

Spring是轻代码而重配置的框架,配置比较繁重,影响开发效率,所以注解开发是一种趋势,注解代替xml配置文件可以简化配置,提高开发效率。

spring原始注解

Spring原始注解主要是替代的配置

在这里插入图片描述

注意:
使用注解进行开发时,需要在applicationContext.xml中配置组件扫描,作用是指定哪个包及其子包下的Bean需要进行扫描以便识别使用注解配置的类、字段和方法。

<!--    配置组件扫描  扫描路径包及其子包-->
    <context:component-scan base-package="com.vector"/>
//<bean id="userDao" class="com.vector.dao.impl.UserDaoImpl"/>
//@Component("userDao")
@Repository("userDao")
public class UserDaoImpl implements UserDao {
    @Override
    public void save() {
        System.out.println("save running...");
    }
}
//<bean id="userService" class="com.vector.service.impl.UserServiceImpl">
//@Component("userService")
@Service("userService")
public class UserServiceImpl implements UserService {
//    <property name="userDao" ref="userDao"/>
  //    @Autowired //自动注入 按照数据类型从Spring容器中进行匹配的
//    @Qualifier("userDao") //要被注入的对象 按照id的名称从容器中进行匹配@Qualifier要结合@Autowired一起使用
    @Resource(name = "userDao") //相当于@Qualifier+@Autowired
    private UserDao userDao; //以反射调用无参构造器赋值
//    public void setUserDao(UserDao userDao){
//        this.userDao = userDao;
//    }
    @Override
    public void save() {
        userDao.save();
    }
}
//测试
public class UserController {
    public static void main(String[] args) {
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService) app.getBean("userService");
        userService.save();
    }
}

在这里插入图片描述
在这里插入图片描述

spring新注解&&完全注解配置

在这里插入图片描述

@Test
/**
 * spring代理druid配置文件连接池
 */
public void getDruidProerties() throws Exception {
    //ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
    ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfiguration.class);
    DataSource dataSource = (DataSource) app.getBean("dataSource");
    Connection conn = dataSource.getConnection();
    System.out.println(conn);
    conn.close();
}

Spring核心配置类

package com.vector.config;


import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

//标志该类是Spring的核心配置类
@Configuration
//<!--    配置组件扫描  扫描路径包及其子包-->
//    <context:component-scan base-package="com.vector"/>
@ComponentScan("com.vector")

//<!--    <import resource=""/>-->
@Import(DataSourceConfiguration.class)
public class SpringConfiguration {

}

Spring数据资源类

package com.vector.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;

import javax.sql.DataSource;
import java.sql.SQLException;

//<!--    加载外部的properties文件-->
//<context:property-placeholder location="classpath:druid.properties"/>
@PropertySource("classpath:druid.properties")
public class DataSourceConfiguration {
    @Value("${jdbc.driverClassName}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;
    @Value("${filters}")
    private String filters;
    @Value("${initialSize}")
    private String initialSize;
    @Value("${maxActive}")
    private String maxActive;
    @Value("${maxWait}")
    private String maxWait;
    @Value("${timeBetweenEvictionRunsMillis}")
    private String timeBetweenEvictionRunsMillis;
    @Value("${minEvictableIdleTimeMillis}")
    private String minEvictableIdleTimeMillis;
    @Value("${validationQuery}")
    private String validationQuery;
    @Value("${testWhileIdle}")
    private String testWhileIdle;
    @Value("${testOnBorrow}")
    private String testOnBorrow;
    @Value("${testOnReturn}")
    private String testOnReturn;
    @Value("${poolPreparedStatements}")
    private String poolPreparedStatements;
    @Value("${maxPoolPreparedStatementPerConnectionSize}")
    private String maxPoolPreparedStatementPerConnectionSize;
    @Bean("dataSource") // Spring会将当前方法的返回值以指定名称存储到Spring容器中
    public DataSource getDataSource() throws SQLException {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        dataSource.setFilters(filters);
        dataSource.setInitialSize(Integer.parseInt(initialSize));
        dataSource.setMaxActive(Integer.parseInt(maxActive));
        dataSource.setMaxWait(Long.parseLong(maxWait));
        dataSource.setTimeBetweenEvictionRunsMillis(Long.parseLong(timeBetweenEvictionRunsMillis));
        dataSource.setMinEvictableIdleTimeMillis(Long.parseLong(minEvictableIdleTimeMillis));
        dataSource.setValidationQuery(validationQuery);
        dataSource.setTestWhileIdle(Boolean.parseBoolean(testWhileIdle));
        dataSource.setTestOnBorrow(Boolean.parseBoolean(testOnBorrow));
        dataSource.setTestOnReturn(Boolean.parseBoolean(testOnReturn));
        dataSource.setPoolPreparedStatements(Boolean.parseBoolean(poolPreparedStatements));
        dataSource.setMaxPoolPreparedStatementPerConnectionSize(Integer.parseInt(maxPoolPreparedStatementPerConnectionSize));
        
        
        
        return dataSource;
    }
}

druid.properties配置文件

jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_test?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
jdbc.username=root
jdbc.password=123456
filters=stat
initialSize=2
maxActive=300
maxWait=60000
timeBetweenEvictionRunsMillis=60000
minEvictableIdleTimeMillis=300000
validationQuery=SELECT 1
testWhileIdle=true
testOnBorrow=false
testOnReturn=false
poolPreparedStatements=false
maxPoolPreparedStatementPerConnectionSize=200

四.spring集成Junit

1.导入spring集成Junit的坐标
2.使用@Runwith注解替换原来的运行期
3.使用@contextconfiguration指定配置文件或配置类使用@Autowired注入需要测试的对象
4.创建测试方法进行测试

注意:
在这里插入图片描述
在这里插入图片描述
可以发现test的实现类引用了main包下的接口,而不是同包下的接口.
当2个的路径名完全一样,编译之后的这这个类肯定只会留一份了,test里面的那个和main里面变成一个了!

package com.test01.test;

import com.test01.config.SpringConfiguration;
import com.test01.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.SQLException;

@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration("classpath:applicationContext.xml")
@ContextConfiguration(classes = {SpringConfiguration.class})
public class SpringJunitTest {
    @Resource(name = "userService")
    private UserService userService;

    @Resource(name = "dataSource")
    private DataSource dataSource;

    @Test
    public void test01() throws SQLException {
        userService.save();
        System.out.println(dataSource.getConnection());

    }
}