Spring依赖注入方法:set注入和构造注入

Spring

  • Spring6启用Log4j2日志框架
  • 依赖注入
    • set注入
      • set注入简单类型
        • 经典案例:给数据源的属性注入值:
      • 注入数组
      • 注入List集合
      • 注入Set集合
      • 注入Map集合
    • 构造注入


Spring6启用Log4j2日志框架

从Spring5之后,Spring框架支持集成的日志框架是Log4j2.如何启用日志框架:
第一步:引入Log4j2的依赖


<dependency>
  <groupId>org.apache.logging.log4jgroupId>
  <artifactId>log4j-coreartifactId>
  <version>2.19.0version>
dependency>
<dependency>
  <groupId>org.apache.logging.log4jgroupId>
  <artifactId>log4j-slf4j2-implartifactId>
  <version>2.19.0version>
dependency>

第二步:在类的根路径下提供log4j2.xml配置文件(文件名固定为:log4j2.xml,文件必须放到类根路径下。)



<configuration>

    <loggers>
        
        <root level="DEBUG">
            <appender-ref ref="spring6log"/>
        root>
    loggers>

    <appenders>
        
        <console name="spring6log" target="SYSTEM_OUT">
            
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss SSS} [%t] %-3level %logger{1024} - %msg%n"/>
        console>
    appenders>

configuration>

第三步:使用日志框架

Logger logger = LoggerFactory.getLogger(FirstSpringTest.class);
logger.info("我是一条日志消息");

依赖注入

● 依赖指的是对象和对象之间的关联关系。
● 注入指的是一种数据传递行为,通过注入行为来让对象和对象产生关系。
依赖注入常见的实现方式包括两种:
● 第一种:set注入
● 第二种:构造注入

新建模块:spring6-003-dependency-injection

set注入

set注入,基于set方法实现的,底层会通过反射机制调用属性对应的set方法然后给属性赋值。这种方式要求属性必须对外提供set方法。

pom.xml


<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.powernodegroupId>
    <artifactId>spring6-002-dependency-injectionartifactId>
    <version>1.0-SNAPSHOTversion>
    <packaging>jarpackaging>

    <repositories>
        <repository>
            <id>repository.spring.milestoneid>
            <name>Spring Milestone Repositoryname>
            <url>https://repo.spring.io/milestoneurl>
        repository>
    repositories>

    <dependencies>
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-contextartifactId>
            <version>6.0.0-M2version>
        dependency>
        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <version>4.13.2version>
            <scope>testscope>
        dependency>
    dependencies>

    <properties>
        <maven.compiler.source>17maven.compiler.source>
        <maven.compiler.target>17maven.compiler.target>
    properties>

project>

UserDao.java

package com.w.spring6.dao;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class UserDao {

    private static final Logger logger= LoggerFactory.getLogger(UserDao.class);
    public void insert(){
        //System.out.println("数据库正在保存信息");
        logger.info("数据库正在保存信息");
    }

}

UserService.java

package com.w.spring6.service;

import com.w.spring6.dao.UserDao;
import com.w.spring6.dao.VipDao;

public class UserService {

    private UserDao userDao;
    private VipDao vipDao;

    public void setAbc(VipDao vipDao){
        this.vipDao=vipDao;
    }


    //set注入的话,必须提供一个set方法
    //spring容器会调用这个set方法,来给userDao赋值
/*    //自己写的不符合javabean规范
    public void setMySQLUserDao(UserDao xyz){
        this.userDao=xyz;
    }*/

    //idea自动生成的符合javabean规范
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void saveUser(){
        userDao.insert();
        vipDao.insert();

    }
}

spring.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="userDaoBean" class="com.powernode.spring6.dao.UserDao"/>

    <bean id="userServiceBean" class="com.powernode.spring6.service.UserService">
        <property name="userDao" ref="userDaoBean"/>
    bean>

beans>

SpringDITest.java

package com.w.spring6.text;

import com.w.spring6.bean.QianDaYe;
import com.w.spring6.bean.User;
import com.w.spring6.jdbc.MyDataSource;
import com.w.spring6.service.CustomerService;
import com.w.spring6.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringDITest {

    @Test
    public void testSetDI(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        UserService userService = applicationContext.getBean("userServiceBean", UserService.class);
        userService.save();
    }
}

运行结果:
Spring依赖注入方法:set注入和构造注入_第1张图片

实现原理:
通过property标签获取到属性名:userDao
通过属性名推断出set方法名:setUserDao
通过反射机制调用setUserDao()方法给属性赋值
property标签的name是属性名。
property标签的ref是要注入的bean对象的id。

总结:set注入的核心实现原理:通过反射机制调用set方法来给属性赋值,让两个对象之间产生关系。

set注入简单类型

之前注入对象属性为UserDao,当对象的属性是int类型时该怎么写

例:编写程序给一个User对象的age属性赋值20:

第一步:定义User类,提供age属性,提供age属性的setter方法。

package com.w.spring6.bean;

public class User {

    private String username;
    private String password;
    private int age;

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

第二步:编写spring配置文件:beans.xml,添加


    <bean id="userBean" class="com.w.spring6.bean.User">
            <property name="username" value="张三"/>
            <property name="password" value="123"/>
            <property name="age" value="20"/>
    bean>

注意:如果给简单类型赋值,使用value属性或value标签。而不是ref

第三步:编写测试程序

    @Test
    public void testSimpleTypeSet() {

        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("beans.xml");
        User user=applicationContext.getBean("userBean", User.class);
        System.out.println(user);
    }

运行结果:
Spring依赖注入方法:set注入和构造注入_第2张图片

经典案例:给数据源的属性注入值:

自己手写一个数据源,所有的数据源都要实现javax.sql.DataSource接口,并且数据源中应该有连接数据库的信息,例如:driver、url、username、password等。

第一步:新建MyDataSource.java,提供4个属性,并提供setter方法。

package com.w.spring6.jdbc;

import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;


/*
所有的数据源都要实现java规范:java.sql.DataSource
什么是数据源:能够给你提供Connection对象的,都是数据源
 */
public class MyDataSource implements DataSource {  //可以把数据源给spring容器管理

    private String driver;
    private String url;
    private String username;
    private String password;

    @Override
    public String toString() {
        return "MyDataSource{" +
                "driver='" + driver + '\'' +
                ", url='" + url + '\'' +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }

    public void setDriver(String driver) {
        this.driver = driver;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }


    @Override
    public Connection getConnection() throws SQLException {
        return null;
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        return null;
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {

    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {

    }

    @Override
    public int getLoginTimeout() throws SQLException {
        return 0;
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }
}

第二步:编写spring配置文件:spring-properties.xml,我们给driver、url、username、password四个属性分别提供了setter方法,我们可以使用spring的依赖注入完成数据源对象的创建和属性的赋值


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


    <context:property-placeholder location="jdbc.properties"/>

        <bean id="dataSource" class="com.w.spring6.jdbc.MyDataSource">
            <property name="driver" value="${jdbc.driverClass}">property>
            <property name="url" value="${jdbc.url}">property>
            <property name="username" value="${jdbc.username}">property>
            <property name="password" value="${jdbc.password}">property>
        bean>

beans>

第三步:编写测试程序

@Test
    public void testProperties() {
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring-properties.xml");
        MyDataSource da=applicationContext.getBean("dataSource", MyDataSource.class);
        System.out.println(da);
    }

运行结果:
Spring依赖注入方法:set注入和构造注入_第3张图片

注入数组

当数组中的元素是简单类型和不是简单类型

QianDaYe.java

package com.w.spring6.bean;

import java.util.Arrays;

public class QianDaYe {

    private String[] aiHaos;

    private Woman[] womens;

    @Override
    public String toString() {
        return "QianDaYe{" +
                "aiHaos=" + Arrays.toString(aiHaos) +
                ", womens=" + Arrays.toString(womens) +
                '}';
    }

    public void setWomens(Woman[] womens) {
        this.womens = womens;
    }

    public void setAiHaos(String[] aiHaos) {
        this.aiHaos = aiHaos;
    }
}

Woman.java

package com.w.spring6.bean;

public class Woman {

    private String name;

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

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

spring-array.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="w1" class="com.w.spring6.bean.Woman">
        <property name="name" value="小花"/>
    bean>

    <bean id="w2" class="com.w.spring6.bean.Woman">
        <property name="name" value="小红"/>
    bean>

    <bean id="w3" class="com.w.spring6.bean.Woman">
        <property name="name" value="小丽"/>
    bean>


    <bean id="yuQian" class="com.w.spring6.bean.QianDaYe">
        <property name="aiHaos">
            <array>
                <value>抽烟value>
                <value>喝酒value>
                <value>打麻将value>
            array>
        property>


        <property name="womens">
            <array>
                <ref bean="w1"/>
                <ref bean="w2"/>
                <ref bean="w3"/>
            array>

        property>


    bean>

beans>

SpringDITest.java

@Test
    public void testArray() {

        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring-array.xml");
        QianDaYe yuQian=applicationContext.getBean("yuQian", QianDaYe.class);
        System.out.println(yuQian);

    }

测试结果:
Spring依赖注入方法:set注入和构造注入_第4张图片

注入List集合

List集合:有序可重复

注意:注入List集合的时候使用list标签,如果List集合中是简单类型使用value标签,反之使用ref标签

People.java

package com.w.spring6.bean;
import java.util.List;


public class People {
    // 一个人有多个名字
    private List<String> names;

    public void setNames(List<String> names) {
        this.names = names;
    }

    @Override
    public String toString() {
        return "People{" +
                "names=" + names +
                '}';
    }
}

spring-collection.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="peopleBean" class="com.w.spring6.bean.People">
        <property name="names">
            <list>
                <value>铁锤value>
                <value>张三value>
                <value>张三value>
                <value>张三value>
                <value>value>
            list>
        property>
    bean>
beans>

测试程序:

    @Test
    public void testCollection(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-collection.xml");
        People peopleBean = applicationContext.getBean("peopleBean", People.class);
        System.out.println(peopleBean);
    }

测试结果:
Spring依赖注入方法:set注入和构造注入_第5张图片

之后的Set集合和Map集合同理,就不演示了

注入Set集合

            <set>
                
                <value>110value>
                <value>120value>
                <value>119value>
            set>

注入Map集合

            <map>
                
                
                <entry key="1" value="北京"/>
                <entry key="2" value="上海"/>
                <entry key="3" value="深圳"/>
            map>

构造注入

核心原理:通过调用构造方法来给属性赋值。

OrderDao

package com.w.spring6.dao;

public class OrderDao {
    public void deleteById(){
        System.out.println("正在删除订单。。。");
    }
}

OrderService

package com.w.spring6.service;

import com.w.spring6.dao.OrderDao;

public class OrderService {
    private OrderDao orderDao;

    // 通过反射机制调用构造方法给属性赋值
    public OrderService(OrderDao orderDao) {
        this.orderDao = orderDao;
    }

    public void delete(){
        orderDao.deleteById();
    }
}

spring.xml添加

    <bean id="orderDaoBean" class="com.w.spring6.dao.OrderDao"/>
    <bean id="orderServiceBean" class="com.w.spring6.service.OrderService">
        
        <constructor-arg index="0" ref="orderDaoBean"/>
    bean>

测试程序:
SpringDITest.java

    @Test
    public void testConstructorDI(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        OrderService orderServiceBean = applicationContext.getBean("orderServiceBean", OrderService.class);
        orderServiceBean.delete();
    }

通过构造方法注入的时候:
● 可以通过下标
● 可以通过参数名
● 也可以不指定下标和参数名,可以类型自动推断。

你可能感兴趣的:(spring,spring,java,后端,开发语言)