• SSM框架-spring中bean的依赖注入


    4 依赖注入方式

    4.1 概述

    1. 依赖注入描述容器中bean和bean中之间的依赖关系的过程,如果bean运行需要的是数字或者字符串呢?
    • 引用类型
    • 简单类型(基本数据类型String)
    1. 类型
    • setter类型
      • 简单类型
      • 引用类型
    • 构造器注入
      • 简单类型
      • 引用类型

    4.2 setter注入

    1. 引用数据类型多个bean的依赖
    • 接口UserDao
    public interface UserDao {
        public void save();
    }
    
    • 1
    • 2
    • 3
    • 接口BookDao
    public interface BookDao {
        void save();
    }
    
    • 1
    • 2
    • 3
    • 接口BookService
    public interface BookService {
        void save();
    }
    
    • 1
    • 2
    • 3
    • 接口实现类UserDaoImpl
    public class UserDaoImpl implements UserDao{
        public void save(){
            System.out.println("user dao save ...");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 接口实现类BookDaoImpl
    public class BookDaoImpl implements BookDao{
        public void save(){
            System.out.println("book dao save");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 接口实现类**[重点]**
    public class BookServiceImpl implements BookService {
        //删除业务层中使用new的方式创建的dao对象
        private BookDao bookDao;
        private UserDao userDao;
    
    
        public void setUserDao(UserDao userDao) {
            this.userDao = userDao;
        }
    
        //生成set方法
        public void setBookDao(BookDao bookDao) {
            this.bookDao = bookDao;
        }
    
    
        public void save(){
            System.out.println("book service save ...");
            bookDao.save();
            userDao.save();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 配置文件
            <bean id ="bookDao" name = "dao" class = "com.itheima.dao.impl.BookDaoImpl"  scope="prototype"/>
            <bean id = "userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
    
            <bean id = "bookService" name = "service bookEbi" class = "com.itheima.service.impl.BookServiceImpl">
                    <property name="bookDao" ref="bookDao"/>
                    <property name="userDao" ref="userDao"/>
            bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • App类
    public class App2 {
        public static void main(String[] args) {
            //3.获取IoC容器,ApplicationContext和配置一样,new一个接口实现类
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    
            BookService bookService = (BookService) ctx.getBean("bookService");
            bookService.save();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 打印结果
    book service save ...
    book dao save
    user dao save ...
    
    Process finished with exit code 0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 简单类型
    • 接口实现类BookDaoImpl
    public class BookDaoImpl implements BookDao{
    
        private int connectionNum;
        private String databaseName;
    
        public void setConnectionNum(int connectionNum) {
            this.connectionNum = connectionNum;
        }
    
        public void setDatabaseName(String databaseName) {
            this.databaseName = databaseName;
        }
        
    
        public void save(){
            System.out.println("book dao save"+databaseName+","+connectionNum);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 配置文件
            <bean id ="bookDao" name = "dao" class = "com.itheima.dao.impl.BookDaoImpl">
                    <property name="databaseName" value="mysql"/>
                    <property name="connectionNum" value="10"/>
            bean>
    
    • 1
    • 2
    • 3
    • 4
    • 打印结果
    book service save ...
    book dao savemysql,10
    user dao save ...
    
    Process finished with exit code 0
    
    • 1
    • 2
    • 3
    • 4
    • 5

    4.3 构造器注入

    1. 引用数据类型
    • 接口实现类BookDaoImpl
    public class BookDaoImpl implements BookDao{
    
        public void save(){
            System.out.println("book dao save");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 接口实现类UserDaoImpl
    public class UserDaoImpl implements UserDao{
        public void save(){
            System.out.println("user dao save ...");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 接口实现类BookServiceImpl【更改之处】
    public class BookServiceImpl implements BookService {
        //删除业务层中使用new的方式创建的dao对象
        private BookDao bookDao;
        private UserDao userDao;
        //private BookDao bookDao = new BookDaoImpl();
    
        //去掉setter方法,进行构造方法构造依赖,记得整两
    
        public BookServiceImpl(BookDao bookDao, UserDao userDao) {
            this.bookDao = bookDao;
            this.userDao = userDao;
        }
    
        public void save(){
            System.out.println("book service save ...");
            bookDao.save();
            userDao.save();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • App入口
    public class App2 {
        public static void main(String[] args) {
            //3.获取IoC容器,ApplicationContext和配置一样,new一个接口实现类
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    
            BookService bookService = (BookService) ctx.getBean("bookService");
            bookService.save();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 配置文件【更改之处】
            <bean id ="bookDao" name = "dao" class = "com.itheima.dao.impl.BookDaoImpl"/>
            <bean id ="userDao" name = "dao" class = "com.itheima.dao.impl.UserDaoImpl"/>
            <bean id = "bookService" class = "com.itheima.service.impl.BookServiceImpl">
                    <constructor-arg name="bookDao" ref="bookDao"/>
                    <constructor-arg name="userDao" ref="userDao"/>
            bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    这边的name表示构造器的形参

    1. 简单类型
    • 实现接口类BookDaoImpl

    也是用的构造器实现的

    public class BookDaoImpl implements BookDao{
    
        private String databaseName;
        private int connectionNum;
    
        public BookDaoImpl(String databaseName, int connectionNum) {
            this.databaseName = databaseName;
            this.connectionNum = connectionNum;
        }
    
        public void save(){
            System.out.println("book dao save"+databaseName+connectionNum);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 配置文件

    这两顺序可以换

            <bean id ="bookDao" class = "com.itheima.dao.impl.BookDaoImpl">
                    <constructor-arg name="databaseName" value="mysql"/>
                    <constructor-arg name="connectionNum" value="666"/>
            bean>
    
    • 1
    • 2
    • 3
    • 4
    • 运行结果
    book service save ...
    book dao savemysql666
    user dao save ...
    
    Process finished with exit code 0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 优化构造器
    • 类型指定

    如果构造器的形参变了,配置文件就得重新配置,出现耦合度比较高的情况,

    因此可以直接写类型,不直接指定形参

            <bean id ="bookDao" class = "com.itheima.dao.impl.BookDaoImpl">
                    <constructor-arg type="java.lang.String" value="mysql"/>
                    <constructor-arg type="int" value="10"/>
            bean>
    
    • 1
    • 2
    • 3
    • 4
    • 位置指定

    但是也可能出现两种类型一样的形参

    于是出现了通过index需要指定

            <bean id ="bookDao" class = "com.itheima.dao.impl.BookDaoImpl">
                    <constructor-arg index="0" value="mysql"/>
                    <constructor-arg index="1" value="100"/>
            bean>
    
    • 1
    • 2
    • 3
    • 4
    • 其他

    4.4 总结

    image.png

    • 构造器注入必须强制执行,setter可以执行也可以不执行

    5 依赖自动装配

    5.1 概念

    IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配

    5.2 种类

    1. 按类型
    2. 按名称
    3. 按构造方法
    4. 不启动自动装配

    5.3 实践

    5.3.1 按照byType匹配

    1. 具体设置
    • 接口实现类BookServiceImpl

    依旧记得保留setter方法

    public class BookServiceImpl implements BookService {
        //删除业务层中使用new的方式创建的dao对象
        private BookDao bookDao;
    //    private BookDao bookDao = new BookDaoImpl();
    
        //生成set方法
        public void setBookDao(BookDao bookDao) {
            this.bookDao = bookDao;
        }
    
        public void save() {
            System.out.println("book service save ...");
            bookDao.save();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 配置文件

    加上autowire就可以了

            <bean id ="bookDao" class = "com.itheima.dao.impl.BookDaoImpl"  scope="prototype"/>
    
            <bean id = "bookService"
                  class = "com.itheima.service.impl.BookServiceImpl" autowire="byType"/>
    
    • 1
    • 2
    • 3
    • 4
    1. 注意点
    • 报错1

    image.png

    image.png

    image.png

    BookServiceImpl中的BookDao与配置文件中的bookDao中bean实现了Dao接口,如果没有就报错

    也就是说是private BookDao bookDao中的BookDao 和

    • 报错2

    image.png

    image.png

    如果满足接口的Dao接口的有两个,就会装配失败

    5.3.2 按照byName匹配

    1. 匹配原则

    image.png

    image.png

    private BookDao bookDao中的bookDao和id ="bookDao"中的bookDao名字要一样,耦合度较高

    1. 配置文件内容

    autowire="byName

            <bean id ="bookDao" class = "com.itheima.dao.impl.BookDaoImpl"  scope="prototype"/>
    
            
            <bean id = "bookService" class = "com.itheima.service.impl.BookServiceImpl" autowire="byName"/>
    
    • 1
    • 2
    • 3
    • 4

    5.3.3 总结

    • 自动装配用于引用类型依赖注入,不能对简单类型进行操作
    • 按类型匹配byType保证容器中相同类型的bean唯一,推荐使用
    • 使用按名称配对byName保证容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用
    • 自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效

    6 集合注入

    6.1 内容

    1. 数组
    2. List
    3. Set
    4. Map
    5. Propertites

    6.2 配置内容

    1. BookDaoImpl接口实现类
    public class BookDaoImpl implements BookDao{
    
        private int[] array;
        private List<String> list;
        private Set<String> set;
        private Map<String,String> map;
        private Properties properties;
    
    
        public void setArray(int[] array) {
            this.array = array;
        }
    
        public void setList(List<String> list) {
            this.list = list;
        }
    
        public void setSet(Set<String> set) {
            this.set = set;
        }
    
        public void setMap(Map<String, String> map) {
            this.map = map;
        }
    
        public void setProperties(Properties properties) {
            this.properties = properties;
        }
    
        public void save(){
            System.out.println("book dao save");
            System.out.println("遍历数组:"+ Arrays.toString(array));
            System.out.println("遍历List:"+list);
            System.out.println("遍历Set:"+set);
            System.out.println("遍历Map:"+map);
            System.out.println("遍历Properties:"+properties);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    1. 配置文件
            <bean id ="bookDao" name = "dao" class = "com.itheima.dao.impl.BookDaoImpl">
    
                    <property name="array">
                       <array>
                            <value>100</value>
                            <value>200</value>
                            <value>300</value>
                           <ref bean="beanId"/>
                       </array>
                    </property>
    
                    <property name="list">
                       <list>
                             <value>itcast</value>
                             <value>itheima</value>
                             <value>boxuegu</value>
                             <value>chuanzhihui</value>
                       </list>
                    </property>
    
                    <property name="set">
                      <set>
                             <value>itcast</value>
                             <value>itheima</value>
                             <value>boxuegu</value>
                      </set>
                    </property>
    
                    <property name="map">
                       <map>
                            <entry key="country" value="china"/>
                            <entry key="province" value="guangdong"/>
                            <entry key="city" value="guangzhou"/>
                        </map>
                    </property>
    
                <property name="properties">
                    <props>
                        <prop key="country">china</prop>
                        <prop key="province">guangdong</prop>
                        <prop key="city">guangzhou</prop>
                    </props>
                </property>
            </bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    7 第三方bean注入:以数据源对象管理为例

    7.1 概述

    第三方的bean该如何管理

    7.2 Druid管理

    1. pom中进行maven文件配置

    Druid是阿里巴巴开发的数据连接池

        <dependency>
          <groupId>com.alibabagroupId>
          <artifactId>druidartifactId>
          <version>1.1.16version>
        dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 判断使用setter还是构造器方法

    image.png

    image.png

    发现DruidDataSource中有setter方法

    1. 配置文件进行配置
            
            <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
                <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/spring_db"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    1. App入口
    public class App2 {
        public static void main(String[] args) {
            //3.获取IoC容器,ApplicationContext和配置一样,new一个接口实现类
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            DataSource dataSource = (DataSource) ctx.getBean("dataSource");
            System.out.println(dataSource);
            
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    1. 结果
    {
    	CreateTime:"2022-11-06 23:08:56",
    	ActiveCount:0,
    	PoolingCount:0,
    	CreateCount:0,
    	DestroyCount:0,
    	CloseCount:0,
    	ConnectCount:0,
    	Connections:[
    	]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    7.3 C3P0连接池管理

    1. mvnrepository中获取配置
    • C3P0

    网址:去Maven Repository: c3p0 » c3p0 » 0.9.1.2 (mvnrepository.com)复制代码

    
    <dependency>
        <groupId>c3p0groupId>
        <artifactId>c3p0artifactId>
        <version>0.9.1.2version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • mysql

    网址:Maven Repository: mysql » mysql-connector-java » 5.1.16 (mvnrepository.com)

    
    <dependency>
        <groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
        <version>5.1.16version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. 加载到maven中
    <dependency>
        <groupId>c3p0groupId>
        <artifactId>c3p0artifactId>
        <version>0.9.1.2version>
    dependency>
    
    <dependency>
        <groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
        <version>5.1.16version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    1. 使用setter注入
    • 配置文件
            <bean id="dataSource2" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    
                <property name="driverClass" value="com.mysql.jdbc.Driver"/>
                <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring_db"/>
                <property name="user" value="root"/>
                <property name="password" value="root"/>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • App入口
    public class App2 {
        public static void main(String[] args) {
            //3.获取IoC容器,ApplicationContext和配置一样,new一个接口实现类
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            DataSource dataSource = (DataSource) ctx.getBean("dataSource2");
            System.out.println(dataSource);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 结果
    com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> 1hge1adasl3sdda8tlh5w|76b0bfab, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 1hge1adasl3sdda8tlh5w|76b0bfab, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://localhost:3306/spring_db, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 15, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> null, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ]
    
    • 1

    8 加载properties文件

    8.1 概述

    1. jbdc.properties配置文件

    image.png

    1. 需求

    需要让spring可以读取识别properties的文件

    8.2 操作

    1. 配置文件中开辟新的空间

    image.png

    
    <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
                    ">
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    1. 加载properties文件
    • 开辟属性占位符,并确定properties的位置
    • 使用${}改变value的值,并读取properties文件中的属性
        
        
        <context:property-placeholder location="jdbc.properties"/>
    
        
        <bean class="com.alibaba.druid.pool.DruidDataSource">
            <property name="driverClassName" value="${jdbc.driver}"/>
            <property name="url" value="${jdbc.url}"/>
            <property name="username" value="${jdbc.username}"/>
            <property name="password" value="${jdbc.password}"/>
        bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    1. 将读出来的值放到name中
    • jdbc.properties
    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://127.0.0.1:3306/spring_db
    jdbc.username=root
    jdbc.password=root
    
    • 1
    • 2
    • 3
    • 4
    • 配置文件增加这一个
        
        <bean id = "bookDao" class="com.itheima.dao.impl.BookDaoImpl">
            <property name="name" value="${jdbc.driver}"/>
        bean>
    
    • 1
    • 2
    • 3
    • 4
    • App实现类
    public class App2 {
        public static void main(String[] args) {
    
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            BookDao bookDao = (BookDao) ctx.getBean("bookDao");
            bookDao.save();
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 结果
    book dao savecom.mysql.jdbc.Driver
    
    Process finished with exit code 0
    
    • 1
    • 2
    • 3
    1. 注意
    • 如果有多个配置文件都要加载

    image.png

    可以用,或者用*

    image.png

    使用classpath表示类路径

    image.png

    使用classpath*表示可以从本工程,或者以及依赖的jar包中读取

    image.png

  • 相关阅读:
    javascript开发五指棋和围棋
    如何进行自动化测试?
    技术分享 | app自动化测试(Android)--触屏操作自动化
    WSL2下使用openocd连接外部调试器开发STM32
    力扣 138. 随机链表的复制
    SpringCloud——微服务
    Mysql优化---锁机制、行锁及表锁
    【Reinforcement Learning】AlphaGo 如何使用的强化学习?
    kubelet源码分析 创建/更新/调谐 pod
    面试官:告诉我为什么static和transient关键字修饰的变量不能被序列化?
  • 原文地址:https://blog.csdn.net/m0_46507516/article/details/127838382