spring6-多种类型的注入方式

OCP原则

ocp指开闭原则,对扩展开放,对修改关闭。是七大原则中最基本的一个原则。

依赖倒置原则(DIP)

什么是依赖倒置原则

核心是面向接口编程、面向抽象编程, 不是面向具体编程。

依赖倒置原则的目的

降低耦合度,提高扩展力

什么是控制反转

控制反转:Ioc(Inversion of Controll),一种编程思想、设计模式。为了降低程序耦合度

反转有两点:

  1. 不在程序中采用硬编码的方式new对象,把创建对象交给别人(UserService userService = new UserServiceImplForMysql())。
  2. 不在程序中采用硬编码的方式维护对象关系。

spring框架

spring实现了Ioc,因此可以创建和维护对象见的关系。

控制反转实现方式主要有 依赖注入(Dependency Injection DI)

依赖注入的方式有以下方式:

  1. Set注入(执行Set方法赋值)
  2. 构造方法注入(执行构造方法赋值)

依赖注入中的“依赖”、“注入”的含义

依赖:A对象和B对象的关系

注入:是一种手段,通过这种手段让A和B产生关系。

依赖注入的实现方式有:set注入和构造方法注入。

set注入

  1. 配置文件配置bean
<!--    配置dao-->
    <bean id="userDao" class="com.ali.dao.UserDao">
    </bean>
<!--    配置Service-->
    <bean id="userService" class="com.ali.service.UserService">
        <!--注入dao,这里的name是 set方法名去掉set字符后剩下的单词首字母小写-->
<!--        ref后面指定要注入的bean的id-->
        <property name="userDao" ref="userDao"/>
    </bean>
  1. 在类中写set方法
package com.ali.service;

import com.ali.dao.UserDao;

public class UserService {

    private UserDao userDao;

    // set注入需要提供一个set方法,方法名以set开头,spring容器调用这个set方法注入UserDao
        public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void saveUser(){
        userDao.insertUser();
    }
}

这样即可注入成功。

注入外部bean

<!--    声明bean-->
    <bean id="orderDao" class="com.ali.dao.OrderDao" />

    <bean id="orderService" class="com.ali.service.OrderService">
<!--    使用ref 来    注入外部bean-->
        <property name="orderDao" ref="orderDao"/>
    </bean>

注入内部bean

    <bean id="orderService2" class="com.ali.service.OrderService">
      <property name="orderDao">
<!--          在property标签中使用嵌套bean,这就是内部bean-->
          <bean class="com.ali.dao.OrderDao" ></bean>
      </property>
    </bean>

注入简单类型

<!--    注入简单类型属性-->
<bean id="userBean" class="com.ali.bean.User">
<!--    简单类型赋值使用value属性-->
    <property name="name" value="张三"></property>
    <property name="age" value="30"></property>
    <property name="password" value="123456"></property>
    </bean>

实际开发中,一般不会吧Date类型当作简单类型,会使用ref来注入Date类型

级联属性赋值

<!--     使用级联属性赋值,给studentBean的clazz属性赋值必须有set、get方法-->
<!--        先配置clazz  再配置clazz.name-->
    <bean id="studentBean" class="com.ali.bean.Student">
        <property name="name" value="李四"></property>
        <property name="clazz" ref="clazzBean"></property>
        <!--级联属性赋值,给studentBean的clazz属性赋值
        这里的clazz是Student类中的属性名
        clazz 必须有set、get方法-->
        <property name="clazz.name" value="高三二班"></property>
    </bean>
    <bean id="clazzBean" class="com.ali.bean.Clazz">
    </bean>

注入数组

   <!--    注入简单类型属性-->
<bean id="userBean1" class="com.ali.bean.User">
<!--    简单类型赋值使用value属性-->
    <property name="name" value="张三"></property>
    <property name="age" value="30"></property>
    <property name="password" value="123456"></property>
    </bean>
    <bean id="userBean2" class="com.ali.bean.User">
        <!--    简单类型赋值使用value属性-->
        <property name="name" value="张三"></property>
        <property name="age" value="30"></property>
        <property name="password" value="123456"></property>
    </bean>
    <bean id="userBean3" class="com.ali.bean.User">
        <!--    简单类型赋值使用value属性-->
        <property name="name" value="张三"></property>
        <property name="age" value="30"></property>
        <property name="password" value="123456"></property>
    </bean>
   
   <bean id="qdyBean" class="com.ali.bean.QDY">
<!--        aihao属性是一个字符串数组-->
        <property name="aihao">
            <array>
                <value>吃</value>
                <value>喝</value>
            </array>
        </property>
<!--        friends是一个User对象数组-->
        <property name="friends">
            <array>
                <ref bean="userBean1"></ref>
                <ref bean="userBean2"></ref>
                <ref bean="userBean3"></ref>
            </array>
        </property>
    </bean>

注入List和Set类型

    <bean id="personBean" class="com.ali.bean.Person">
<!--        names是 List<String> 类型-->
        <property name="names">
            <list>
                <value>张三</value>
                <value>里斯</value>
                <value>詹姆思</value>
            </list>
        </property>
<!--        address 是 Set<String>   类型-->
        <property name="address">
            <set>
                <value>北京</value>
                <value>上海</value>
                <value>广州</value>
            </set>
        </property>
    </bean>

注入Map集合

<!--      phone 是一个Map<Integer, String>类型
      如果key是简单类型,可以直接使用entry标签的key属性赋值
      如果key是复杂类型,可以使用
      <entry key-ref="keyBean" value-ref="valueBean"></entry>
      value同理-->
      <property name="phone">
          <map>
              <entry key="1" value="13800138000"></entry>
              <entry key="2" value="13900139000"></entry>
              <entry key="3" value="13700137000"></entry>
          </map>
      </property>

注入Properties类型

<!--        Properties 的key 和value只能是字符串类型-->
        <property name="properties">
            <props>
                <prop key="k1">v1</prop>
                <prop key="k2">v2</prop>
                <prop key="k3">v3</prop>
            </props>
        </property>

注入null和空字符串

<!--        以下是手动注入null-->
        <property name="name" >
            <null></null>
        </property>
        <!--        不给属性注入,属性的默认值是null-->
<!--        <property name="name" value="tom"></property>-->
<!--       注入空字符串方式一 -->
        <property name="name" value=""></property>
<!--        注入空字符串方式二 -->
        <property name="name" >
            <value></value>
        </property>
        <property name="age" value=“31”></property>

注入特殊字符串

 <bean id="mathBean" class="com.ali.bean.MathBean">
        <!--     第一种:使用实体符号代替特殊符号    2<3 -->
<!--        <property name="result" value="2 &lt; 3"></property>-->
        <!--     第二种:使用<![CDATA[]]> 这里面的内容不会被xml解析    2<3 -->
        <property name="result">
<!--            只能使用value标签-->
            <value><![CDATA[2<3]]></value>
        </property>
    </bean>

构造注入

  1. 配置文件配置bean
    <bean id="userDaoBean" class="com.ali.dao.UserDao">
    </bean>
<!--     构造注入-->
    <bean class="com.ali.service.CustomerService" id="customerService">
<!--        指定构造方法的第一个参数,下标是0-->
        <constructor-arg index="0" ref="userDaoBean"></constructor-arg>
        <!--        根据参数名注入-->
        <constructor-arg name="userDao" ref="userDaoBean“></constructor-arg>
    </bean>
  1. 在类中写构造方法
public class CustomerService {

    private UserDao userDao;

    public CustomerService(UserDao userDao) {
        this.userDao = userDao;
    }

    public  void save(){
        userDao.insertUser();
    }
}

p命名空间注入(简化set注入)

<!--  p命名空间注入底层还是set注入(类中的属性必须有set方法),只不过p命名空间注入让spring配置更加简单
  1.在spring配置文件头部添加p命名空间。  xmlns:p="http://www.springframework.org/schema/p"
  2.使用p命名空间注入属性,语法:p:属性名="属性值"  p:属性名-ref="引用类型属性值"-->
  <bean id="dogBean" class="com.ali.bean.Dog" p:age="22" p:name="张三" p:birthday-ref="birthdayBean"/>

  <bean id="birthdayBean" class="java.util.Date" />

c命名空间注入(简化构造注入)

<!--  c命名空间注入底层还是构造器注入(类中必须有对应的构造器),只不过c命名空间注入让spring配置更加简单
  1.在spring配置文件头部添加c命名空间。  xmlns:c="http://www.springframework.org/schema/c"
  2.使用c命名空间注入属性,语法:c:属性名="属性值"  c:属性名-ref="引用类型属性值"
  c:_0 下标方式   c:name  参数名方式-->
<bean id="peopleBean" class="com.ali.bean.People" c:name="咪咪" c:age="3" c:sex="true"/>

基于xml的自动装配byName

<!--        自动装配:byName、 也是基于set的-->
<!--    根据名字自动装配,其中OrderDao是OrderService里面的一个属性。必须有set方法-->
    <bean id="orderServiceBean" class="com.ali.service.OrderService" autowire="byName"></bean>

<!--    这个id 必须是OrderService中set方法去掉“set”后首字母小写-->
    <bean id="orderDao" class="com.ali.dao.OrderDao"></bean>

基于xml的自动装配byType

<!--     根据类型自动装配,自动装配是基于set方法的
         根据类型进行自动装配时,配置文件中某个类型的实例只能有一个
         -->
    <bean class="com.ali.dao.VipDao"></bean>
    <bean class="com.ali.dao.UserDao"></bean>
<!--    CustomerService类里面VipDao和UserDao属性,这2个属性必须有set方法才能自动注入上面2个bean-->
    <bean id="customerServiceBean" class="com.ali.service.CustomerService" autowire="byType"></bean>

</beans>

引入外部的属性配置文件

   <!-- 引入外部的properties文件
     第一步:引入context命名空间 xmlns:context="http://www.springframework.org/schema/context"
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
     第二步:使用<context:property-placeholder>标签引入外部的properties文件,默认从类的根路径下加载
     -->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <bean id="mydataSource" class="com.ali.bean.MyDataSource">
        <!-- 使用${}占位符引用外部properties文件中的属性值 这4个属性必须有set方法-->
        <property name="driver" value="${jdbc.diverClass}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

jdbc.properties文件

jdbc.diverClass=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring6db?useSSL=false&server
jdbc.username=root
jdbc.password=123456

spring怎么实例化对象?

默认情况下spring通过反射机制,调用类的无参数构造方法实例化对象

把创建好的对象存储到Map结构中。

当有多个配置文件时,可读取多个配置文件

ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml","spring-dao.xml");

可以在配置文件中注入jdk自带的类,只要这个类有无参数构造方法就行。

getBean()时,Bean的id不存在时会报错

从类路径之外的路径获取xml配置文件

// 读取类路径之外的配置文件
ApplicationContext context = new FileSystemXmlApplicationContext("D:/applicationContext.xml");
Object user=  context.getBean("user"); // 获取spring容器中的对象

ApplicationContext的超级父接口是BeanFactory。

BeanFactory是Ioc容器的顶级接口。

spring的Ioc容器底层使用了工厂模式。

启用Log4j2

spring5之后支持Log4j2框架。

  1. 引入依赖
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j2-impl</artifactId>
    <version>2.19.0</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.19.0</version>
</dependency>
  1. 编写配置文件,文件名必须是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>
  1. 使用日志框架 ,在SpringTest01类中使用如下代码
Logger logger = LoggerFactory.getLogger(SpringTest01.class);
logger.info("日志信息");
posted @ 2026-02-02 12:12  NE_STOP  阅读(8)  评论(0)    收藏  举报