spring依赖注入方式和开发中的小应用(xml形式)

spring依赖注入方式和小案例(xml形式)

控制反转(IOC)说的是创建对象由spring容器帮我们完成,不是我们自己去new,依赖注入(DI)是在控制反转的基础上实现的,为一个对象注入属性值(这个过程由容器完成)。

一:区分概念:

当某个java对象(调用者/使用者)需要调用/使用另一个Java对象(调用者,即依赖对象,这里注意区分依赖于别人和被别人依赖的关系,被依赖就是自身被他人需要)时,在传统模式下。我们一般使用new被调用者的方式来创建对象。这种方式会导致代码的耦合性强,不易于代码后期的维护和升级。

依赖注入:

DI:依赖注入,就是注入属性(在创建对象的基础上才能注入属性)

站在spring容器的角度去描述:spring容器负责将需要的对象注入(赋值)到调用者的成员变量。即为调用者注入了它依赖的实例。这就是依赖注入。

控制反转:

站在调用者角度去描述:原先我们是在调用者的代码中直接控制被调用者。类似于这样new 对象。

下面展示一些 内联代码片

public class Car {
    private String name;//汽车的名字
    //Engine为我么自定义个的一个发动机类,这里我们汽车依赖于发动机这个 对象。
    //而站在发动机角度看:发动机被汽车所依赖,所以发动机是被依赖对象/被调用者
    private Engine v8 = new Engine();//调用者直接控制被依赖对象,耦合性太强。
}

而现在有了spring容器后,对象的实例不是由调用者自己去new创建,而是由spring容器帮我们完成。站在调用者的角度去看,原先自己控制对象的创建权交给了容器。控制权发生了反转。这就是控制反转(对象的创建权反转)

二:依赖注入的实现方式:通常是这两种,构造方法/构造器注入和属性setter方法注入===重点是bean的装配和属性的设置。

依赖注入的实现方式:构造方法和set方法
方式一:属性setter方式注入:指的是spring容器使用setter方法注入被依赖的实例,通过先调用无参构造器或无参静态工厂方法实例化(相当于java类中的创建对象,Car car= new Car();)Bean后,再调用该bean的setter方法(相当于java中的car.setEngine(new Engine() ),将发动机注入汽车等),即可实现基于setter方法的依赖注入。

方式二:构造方法注入:指spring容器使用构造方法注入被依赖的实例。 基于构造方法的依赖注入通过调用带参数的构造方法来实现。每个参数代表一个依赖。

这里我们研究set方式的注入:在容器的内部,将UserDao 设置到UserService内部,获取UserServiec实例,内部已经存在UserDao实例了,直接调用UserDao的save()方法即可

**依赖注入/(bean的装载方式)的setter注入(设值注入)

第一步操作:在对象中配置需要依赖的另一个bean,设置属性和对应的setter方法。这里的属性是对象的引用。这里对应于配置文件的
<bean id="userService" class="com.fan.service.impl.UserServiceImpl">
第二步操作:在applicationContext中配置bean,现在使用对象的相当于消费者,而容器相当于生产者,消费者不再管对象的生产,他们需要的所有对象都是间接去容器中(相当于网上的商城)拿的。而我们需要做的是将对象(商品)上架到配置到容器中(上货到网上商城),这样消费者才能看到这些商品去购买使用。**

注入引用类型:

Java类UserServiceImpl中的操作:
下面展示一些 内联代码片

package com.fan.service.impl;

import com.fan.dao.UserDao;
import com.fan.domain.User;
import com.fan.service.UserService;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserServiceImpl implements UserService {
    //依赖注入的set方式的第一步:设置属性和set方法。这里的属性是对象的引用。
    private UserDao userDao;//抽象的接口集成进来
    public void setUserDao(UserDao userDao) {//为所有的属性提供setter方法。
        this.userDao = userDao;
    }
    @Override
    public void save() {
        //直接使用userDao的save()方法,不用从容器获得dao了,在容器内部通过set方法注入给我了。那我们声明的userDao就
        //不是null了。代码写完后容器不知道。还要配置spring容器
        userDao.save(new User());
    }
}

二:配置文件中的操作方式一 :

下面展示一些 内联代码片

<!--UserDaoImpl是被依赖对象/被调用对象-->
<bean id="userDao" class="com.fan.dao.impl.UserDaoImpl"></bean>
<!--1.通过注解的方式相当于创建一个空的对象 对象id,对象对应类所在的全限定名-->
<bean id="userService" class="com.fan.service.impl.UserServiceImpl">
    <!--2.在一个对象中声明引用 另一个对象。也就是这大对象设置属性,只不过这个属性是引用类型。 属性名 是大对象中的set方法后的名字首字母小写,属性值是一个bean的id-->
    <property name="userDao" ref="userDao"></property><!--name="userDao"是setUserDao方法-->
</bean>

代码讲解:
是元素的子元素,它用于调用bean实例中的setUserDao()方法完成属性赋值,从而实现依赖注入,其name属性表示bean实例中的相应属性,ref是当前配置文件中对象的id引用。
配置文件中的操作方式二 :命名空间
下面展示一些 内联代码片

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--这里的id 相当于我们原先的接口的返回值 后面相当于我们要new  的 对象的全限定名 -->
 <bean id="userDao" class="com.fan.dao.impl.UserDaoImpl"></bean>

 <bean id="userService" class="com.fan.service.impl.UserServiceImpl" p:userDao-ref="userDao"></bean>
 </beans>

Ref引用的都是bean的Id;记住了;

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

注入普通的属性:UserServiceImpl实现类

下面展示一些 内联代码片

package com.fan.service.impl;

import com.fan.dao.UserDao;
import com.fan.domain.User;
import com.fan.service.UserService;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserServiceImpl implements UserService {
    //注入普通的属性,用value
    private String name;
    private int age;

    public void setName(String name) {
        this.name = name;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public void save() {
        System.out.println(name+":"+age);
    }
}

测试类:

下面展示一些 内联代码片

package com.fan.demo;

import com.fan.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestJave {
    @Test
    public void test1(){
        ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService) app.getBean("userService2");
        userService.save();
    }
}

ApplicationContext文件
下面展示一些 内联代码片

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--这里的id 相当于我们原先的接口的返回值 后面相当于我们要new  的 对象的全限定名 -->
    <bean id="userDao" class="com.fan.dao.impl.UserDaoImpl"></bean>

    <bean id="userService2" class="com.fan.service.impl.UserServiceImpl">
        <property name="name" value="张三"></property>
        <property name="age" value="18"></property>
    </bean>
</beans>

注入集合等

配置文件:
下面展示一些 内联代码片

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--这里的id 相当于我们原先的接口的返回值 后面相当于我们要new  的 对象的全限定名 -->


    <bean id="userService2" class="com.fan.service.impl.UserServiceImpl" >
        <property name="strList" >
            <list>
                <value>a</value>
                <value>b</value>
                <value>c</value>

            </list>
        </property>
        <property name="userMap">
            <map>
                <entry key="u1"  value-ref="user1"></entry>
            </map>
        </property>
        <property name="properties">
            <props>
                <prop key="p1">pp1</prop>
                <prop key="p2">pp2</prop>
            </props>
        </property>
    </bean>
    <bean id="user1" class="com.fan.domain.User">
        <property name="name" value="tom"></property>
        <property name="age" value="23"></property>
    </bean>

</beans>

类文件:
下面展示一些 内联代码片

package com.fan.service.impl;

import com.fan.dao.UserDao;
import com.fan.domain.User;
import com.fan.service.UserService;

import java.util.List;
import java.util.Map;
import java.util.Properties;

public class UserServiceImpl implements UserService {
    //注入集合等
    private List<String> strList;
    private Map<String,User> userMap;
    private Properties properties;

    public void setStrList(List<String> strList) {
        this.strList = strList;
    }

    public void setUserMap(Map<String, User> userMap) {
        this.userMap = userMap;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    public void save() {
        System.out.println(strList);
        System.out.println(userMap);
        System.out.println(properties);
    }
}

实体类文件:
下面展示一些 内联代码片

package com.fan.domain;

public class User {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

数据库配置文件的加载和注入

spring容器加载外部配置数据源文件
第一步:编写jdbc.properties文件(数据库的部分信息)

下面展示一些 内联代码片

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=root

第二步:Spring容器application.xml的配置,在resources下右键新键一个xml.如图
在这里插入图片描述
编写技巧和步骤说明:
1.将xmlns="http://www.springframework.org/schema/beans"这一行代码复制,粘贴到下一行的空行位置,然后将xmlns后加命名空间 :context,将其后的beans都换成context.变成这样:xmlns:context="http://www.springframework.org/schema/context"

2.添加schema约束,将schemaLocation后的双引号中的内容都整体复制一份,然后复制到双引号内 的后面,并将其中的所有beans换成context就可以了。如以下代码:
下面展示一些 内联代码片

<?xml version="1.0" encoding="UTF-8"?>
<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:jdbc.properties"></context:property-placeholder>
        <bean id="ds" 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>

</beans>

在这里插入图片描述

3.spring加载了数据库配置文件后,就需要将这些配置信息通过setter注入到对象的属性值中去,不然对象的属性值会为空的。(通过DruidDataSource
类中个setter方法注入普通的属性值)

在这里插入图片描述

第三步:编写测试类UserController,当控制台打印出jdbc的类信息就证明成功了。
下面展示一些 内联代码片

package com.fan.web;

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

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

public class UserController {
    public static void main(String[] args) throws SQLException {
        //加载spring容器
        ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("app.xml");
        DataSource ds = (DataSource) app.getBean("ds");//获取数据库连接池对象
        Connection connection = ds.getConnection();//从池子中获取连接对象
        System.out.println(connection);//打印此连接
        connection.close();//归还连接
    }
}

测试类图片:
在这里插入图片描述

再附上 spring和druid配置:

<!-- 引入配置文件 -->
    <bean id="propertyConfigurer"
          class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:jdbc.properties"/>
    </bean>
    <!-- JDBC Data Source. It is assumed you have MySQL running on localhost
    port 3306 with username root and blank password. Change below if it's not
    the case -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
    <property name="driverClassName" value="${driver}"/>
    <!-- 基本属性 url、user、password -->
    <property name="url" value="${url}"/>
    <property name="username" value="${username}"/>
    <property name="password" value="${password}"/>

    <!-- 配置初始化大小、最小、最大 -->
    <property name="initialSize" value="1"/>
    <property name="minIdle" value="1"/>
    <property name="maxActive" value="20"/>

    <!-- 配置获取连接等待超时的时间 -->
    <property name="maxWait" value="60000"/>

    <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
    <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"/>

    <!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
    <property name="poolPreparedStatements" value="false"/>
    <property name="maxPoolPreparedStatementPerConnectionSize" value="20"/>

    <!-- 配置监控统计拦截的filters -->
    <property name="filters" value="stat"/>
    </bean>

二、结尾

总结,记住每一种方式的语法格式和代表的意思就ok了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值