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


Spring6启用Log4j2日志框架

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

<!--log4j2的依赖-->
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-core</artifactId>
  <version>2.19.0</version>
</dependency>
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-slf4j2-impl</artifactId>
  <version>2.19.0</version>
</dependency>

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

<?xml version="1.0" encoding="UTF-8"?>

<configuration>

    <loggers>
        <!--
            level指定日志级别,从低到高的优先级:
                ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF
        -->
        <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

<?xml version="1.0" encoding="UTF-8"?>
<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.0</modelVersion>
    <groupId>com.powernode</groupId>
    <artifactId>spring6-002-dependency-injection</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <repositories>
        <repository>
            <id>repository.spring.milestone</id>
            <name>Spring Milestone Repository</name>
            <url>https://repo.spring.io/milestone</url>
        </repository>
    </repositories>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.0-M2</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.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

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

    <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();
    }
}

运行结果:
在这里插入图片描述

实现原理:
通过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);
    }

运行结果:
在这里插入图片描述

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

自己手写一个数据源,所有的数据源都要实现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的依赖注入完成数据源对象的创建和属性的赋值

<?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命名空间
第二步:使用标签location属性来指定属性配置文件的路径

-->

    <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);
    }

运行结果:
在这里插入图片描述

注入数组

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

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

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

    <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);

    }

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

注入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

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

    <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);
    }

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

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

注入Set集合

            <set>
                <!--非简单类型可以使用ref,简单类型使用value-->
                <value>110</value>
                <value>120</value>
                <value>119</value>
            </set>

注入Map集合

            <map>
                <!--如果key不是简单类型,使用 key-ref 属性-->
                <!--如果value不是简单类型,使用 value-ref 属性-->
                <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">
        <!--index="0"表示构造方法的第一个参数,将orderDaoBean对象传递给构造方法的第一个参数。-->
        <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();
    }

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

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值