Spring6中如何实现多种类型的依赖注入方式?

摘要:OCP原则 ocp指开闭原则,对扩展开放,对修改关闭。是七大原则中最基本的一个原则。 依赖倒置原则(DIP) 什么是依赖倒置原则 核心是面向接口编程、面向抽象编程, 不是面向具体编程。 依赖倒置原则的目的 降低耦合度,提高扩展力 什么是控制
OCP原则 ocp指开闭原则,对扩展开放,对修改关闭。是七大原则中最基本的一个原则。 依赖倒置原则(DIP) 什么是依赖倒置原则 核心是面向接口编程、面向抽象编程, 不是面向具体编程。 依赖倒置原则的目的 降低耦合度,提高扩展力 什么是控制反转 控制反转:Ioc(Inversion of Controll),一种编程思想、设计模式。为了降低程序耦合度 反转有两点: 不在程序中采用硬编码的方式new对象,把创建对象交给别人(UserService userService = new UserServiceImplForMysql())。 不在程序中采用硬编码的方式维护对象关系。 spring框架 spring实现了Ioc,因此可以创建和维护对象见的关系。 控制反转实现方式主要有 依赖注入(Dependency Injection DI) 依赖注入的方式有以下方式: Set注入(执行Set方法赋值) 构造方法注入(执行构造方法赋值) 依赖注入中的“依赖”、“注入”的含义 依赖:A对象和B对象的关系 注入:是一种手段,通过这种手段让A和B产生关系。 依赖注入的实现方式有:set注入和构造方法注入。 set注入 配置文件配置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> 在类中写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> 构造注入 配置文件配置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> 在类中写构造方法 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框架。 引入依赖 <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> 编写配置文件,文件名必须是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> 使用日志框架 ,在SpringTest01类中使用如下代码 Logger logger = LoggerFactory.getLogger(SpringTest01.class); logger.info("日志信息");