spring-IOC

IOC容器

简介

IoC(Inversion of Control)控制反转,是一种基于面向对象编程法则的设计思想,它设计出的程序具有松耦合、更优良的特点。
IoC容器是Spring框架中重要的核心组件之一,贯穿了Spring从出生到成长的整个过程,Spring通过IoC容器管理所有Java对象的实例化和初始化,控制对象与对象之间的实例化、初始化以及依赖关系。由IoC容器管理的Java对象称为Spring Bean,它与使用new 关键字创建的Java对象没有任何区别。

Bean管理:Bean对象的创建和Bean对象中属性的的赋值(或者叫Bean对象之间关系的维护)

控制反转,反转的是什么?

  • 将对象的创建权交出去,交给第三方容器负责。
  • 将对象和对象之间关系的维护权交出去,交给第三方容器负责。

如何实现控制反转?

DI(Dependency Injection) 依赖注入

依赖注入:指Spring创建对象的过程中,将对象依赖属性通过配置进行注入,它实现了控制反转的思想。当一个对象作为另一个对象的属性的时候,我们可以使用依赖注入的方式将对象的内容注入。

依赖注入的实现方式:①set注入、②构造注入


IoC在Spring中的实现

Spring的IoC容器中管理的组件叫做Bean, 在创建Bean之前,首先需要创建IoC容器,Spring提供的IoC容器有两种实现方式。

1、BeanFactory
这是IoC容器的基本实现,是Spring内部使用的接口
2、ApplicationContext
BeanFactory的子接口,提供了更多高级特性。面向Spring的使用者,几乎所有的场合都使用ApplicationContext而不是底层的BeanFactory

ApplicationContext的主要实现类

在这里插入图片描述

类名简介
ClassPathXmlApplicationContext通过类读取路径下的XML格式的配置文件创建IoC对象
FileSystemXmlApplicationContext通过文件系统路径读取XML格式的配置文件创建IoC对象
ConfigurableApplicationContextApplicationContext的子接口,包含一些扩展方法refresh()和close(),让ApplicationContext具有启动、关闭和刷新上下文功能
WebApplicationContex专门为Web应用准备,基于Web环境创建的IoC容器对象,并将对象引入存入ServletContext域中

基于xml管理Bean

步骤

①导入相关依赖

<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>6.0.9</version>
</dependency>
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope>
</dependency>
<dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.20.0</version>
</dependency>
<dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-slf4j2-impl</artifactId><version>2.20.0</version>
</dependency>

②创建spring和log4j2的配置文件

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="user" class="com.louis.ioc_xml.User"></bean>
</beans>

log4j2的配置文件可从取:https://blog.csdn.net/xry12354/article/details/131647570

③创建User对象

package com.louis.ioc_xml;/*** @author XRY* @date 2023年06月22日13:58*/
public class User {private String name;private Integer age;public void run(){System.out.println("run....");}
}

④获取Bean

方式一:根据id获取

由于id属性指定了bean的唯一标识,所以根据bean标签的id属性可以精确获取到一个组件对象。
写法:

<bean id="user" class="com.louis.ioc_xml.User"></bean>

id属性:唯一标识
class属性:要创建对象所在类的全路径(包名称+类名称)

@Test
public void testBeanById(){ApplicationContext applicationContext =new ClassPathXmlApplicationContext("bean.xml");User user = (User)applicationContext.getBean("user");logger.info("user = " + user);
}
/*[2023-06-22 14:17:20:953] [INFO] - TestBeanById.testBeanById(TestBeanById.java:20) - user = com.louis.ioc_xml.User@77d2e85*/

方式二:根据类型获取

@Test
public void testBeanByClass(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");User bean = applicationContext.getBean(User.class);logger.info("user"+bean);
}
/*[2023-06-22 14:22:24:009] [INFO] - TestBeanById.testBeanByClass(TestBeanById.java:29) - usercom.louis.ioc_xml.User@1a9c38eb*/

方式三:根据id和类型获取

@Test
public void testBeanByClassAndId(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");User user = applicationContext.getBean("user", User.class);logger.info("user" + user);
}
/*[2023-06-22 14:25:27:189] [INFO] - TestBeanById.testBeanByClassAndId(TestBeanById.java:37) - usercom.louis.ioc_xml.User@77d2e85*/

获取bean的细节

根据类型获取Bean时,要求IoC容器中指定类型的bean有且只能有一个。
组件类实现了接口,如果实现类只有一个则可以通过类型获取bean,如果实现类有多个,即使这些实现类都配置了bean也不能够使用类型获取。

只有一个实现类

//UserDaoImpl
package com.louis.bean;/*** @author XRY* @date 2023年06月22日14:37*/
public class UserDaoImpl implements UserDao{@Overridepublic void run() {System.out.println("check the target");}
}

测试

@Test
public void testInterface(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");UserDao userDao = applicationContext.getBean("userDao", UserDao.class);logger.info("userDao" + userDao);userDao.run();
}
/*[2023-06-22 14:43:27:092] [INFO] - TestBeanById.testInterface(TestBeanById.java:47) - userDaocom.louis.bean.UserDaoImpl@58ffcbd7check the target*/

User有多个实现类

//PersonDaoImpl
package com.louis.bean;/*** @author XRY* @date 2023年06月22日14:47*/
public class PersonDaoImpl implements UserDao{@Overridepublic void run() {System.out.println("person");}
}

测试

@Test
public void testTwoInterface(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");UserDao personDao = (UserDao)applicationContext.getBean("personDao");logger.info("personDao" + personDao);UserDao bean = applicationContext.getBean(UserDao.class);logger.info("bean" + bean);
}/*[2023-06-22 14:55:05:632] [INFO] - TestBeanById.testTwoInterface(TestBeanById.java:57) - personDaocom.louis.bean.PersonDaoImpl@555cf22org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.louis.bean.UserDao' available: expected single matching bean but found 2: userDao,personDao*/
结论

根据类型来获取bean时,在满足bean唯一性的前提下,其实只是看instanceof指定的类型的返回结果,只要返回的结果是true就可以认定为和类型匹配,能够获取到。
java中instanceof运算符用来判断前面的对象是否是后面的类,或其子类、实现类的实例。如果是返回true,否则返回false。


依赖注入

创建对象过程中,给属性设置值。

原生方法实现

package com.louis.di;/*** @author XRY* @date 2023年06月23日9:46*/
public class Book {private String name;private String author;public Book() {}public Book(String name, String author) {this.name = name;this.author = author;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public static void main(String[] args){//使用原生方法实现值的设置//setBook book = new Book();book.setName("西游记");book.setAuthor("吴承恩");//构造器Book book1 = new Book("水浒传","施耐庵");}
}

基于setter注入

步骤

1、创建类,定义属性生成属性的set方法

package com.louis.di;/*** @author XRY* @date 2023年06月23日9:46*/
public class Book {private String name;private String author;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}@Overridepublic String toString() {return "Book{" +"name='" + name + '\'' +", author='" + author + '\'' +'}';}
}

2、在spring的配置文件中进行配置

<!--基于set方法进行注入-->
<bean id="book" class="com.louis.di.Book">
<!--在使用property这个标签时,就会调用类中的set方法--><property name="name" value="红楼梦"></property><property name="author" value="曹雪芹"></property>
</bean>

3、测试

@Test
public void testBook(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean-di.xml");Book book = applicationContext.getBean("book", Book.class);logger.info("set注入" + book);
}/*[2023-06-23 10:02:10:517] [INFO] - TestBeanById.testBook(TestBeanById.java:72) - set注入Book{name='红楼梦', author='曹雪芹'}*/

基于构造器注入

步骤

1、创建类,定义属性,生成有参构造方法(可以没有无参)

package com.louis.di;/*** @author XRY* @date 2023年06月23日9:46*/
public class Book {private String name;private String author;public Book() {}public Book(String name, String author) {this.name = name;this.author = author;}@Overridepublic String toString() {return "Book{" +"name='" + name + '\'' +", author='" + author + '\'' +'}';}
}

2、在spring中进行配置

<!--构造器注入-->
<bean id="bookConstructor" class="com.louis.di.Book"><constructor-arg name="name" value="三国演义"></constructor-arg><constructor-arg name="author" value="罗贯中"></constructor-arg>
<!--也可以使用index这种类型<constructor-arg index="0" value="三国"></constructor-arg>-->
</bean>

3、测试

@Test
public void testConstructor(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean-di.xml");Book bookConstructor = applicationContext.getBean("bookConstructor", Book.class);logger.info("bookCon" + bookConstructor);
}
/*有参构造方法执行了
[2023-06-23 10:13:15:457] [INFO] - TestBeanById.testConstructor(TestBeanById.java:81) - bookConBook{name='三国演义', author='罗贯中'}*/

注入过程中特殊值的处理

字面量赋值

字面量
如:int a = 1;直接赋值,表示我们看到的这个数据本身。

<!-- 使用value属性给bean的属性赋值时,Spring会把value属性的值看做字面量 -->
<property name="name" value="张三"/>

null值

<bean id="book" class="com.louis.di.Book">
<!--在使用property这个标签时,就会调用类中的set方法--><property name="name" value="红楼梦"></property><property name="author"><null></null></property>
</bean>

xml实体

当设置的值中有类似<>的时候,需要进行转义处理。解决方案:用xml实体来代替

 <property name="name" value="&lt;&gt;"></property>

CDATA节

它是xml中一种特殊的写法,当设置的值中有类似<>的时候,就是要写<>时可以使用。

<property name="name"><!--CDATA节中写什么符号都随意--><value><![CDATA[ < >]]></value>
</property>

不同类型进行依赖注入

对象类型属性注入

如:部门和员工

Department
public class Department {private String dName;public void info(){System.out.println("Department name");}
}
Employee
public class Employee {private String eName;private Integer age;private Department dept;public void work(){System.out.println("Employee working");}
}
方式一:引用外部bean
1、生成它们的set方法

Department

//部门类
public class Department {private String dname;public String getDname() {return dname;}public void setDname(String dname) {this.dname = dname;}public void info(){System.out.println("Department name");}
}

Employee

public class Employee {private String eName;private Integer age;private Department dept;public String geteName() {return eName;}public void seteName(String eName) {this.eName = eName;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Department getDept() {return dept;}public void setDept(Department dept) {this.dept = dept;}public void work(){System.out.println("Employee working");//为了验证引入是否成功dept.info();}
}
2、编写配置文件
<!--引入外部bean1、创建两个类对象:department和employee2、在Employee标签里面,使用property引入两个类-->
<bean id="dept" class="com.louis.di_test.Department"><property name="dname" value="IT"></property>
</bean>
<bean id="emp" class="com.louis.di_test.Employee"><property name="eName" value="Alex"></property><property name="age" value="18"></property>
<!--注入对象类型的熟属性--><property name="dept" ref="dept"></property>
</bean>
3、测试
@Test
public void testObj(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean-diTest.xml");Employee emp = applicationContext.getBean("emp", Employee.class);emp.work();logger.info("emp" + emp);
}
/*Employee working
Department name
[2023-06-23 11:45:56:941] [INFO] - TestBeanById.testObj(TestBeanById.java:92) - empEmployee{eName='Alex', age=18, dept=Department{dname='IT'}}
*/
方式二:内部bean
1、生成set方法
2、编写配置文件
<!--内部bean注入-->
<bean id="emp2" class="com.louis.di_test.Employee"><property name="eName" value="Louie"></property><property name="age" value="20"></property><!--内部bean--><property name="dept"><bean id="dept2" class="com.louis.di_test.Department"><property name="dname" value="设计"></property></bean></property>
</bean>
3、测试
@Test
public void testObj2(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean-diTest.xml");Employee emp2 = applicationContext.getBean("emp2", Employee.class);emp2.work();logger.info("emp2" + emp2);
}
/*
Employee working
Department name
[2023-06-23 11:54:58:543] [INFO] - TestBeanById.testObj2(TestBeanById.java:104) - emp2Employee{eName='Louie', age=20, dept=Department{dname='设计'}}
*/
方式三:级联属性赋值
1、创建实体对象,生成set方法
2、编写配置文件
<!--级联赋值-->
<bean id="dept3" class="com.louis.di_test.Department"><property name="dname" value="超人组"></property>
</bean>
<bean id="emp3" class="com.louis.di_test.Employee"><property name="eName" value="khan"></property><property name="age" value="23"></property><property name="dept" ref="dept3"></property><property name="dept.dname" value="研发科"></property>
</bean>
3、测试
@Test
public void testObj3(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean-diTest.xml");Employee emp3 = applicationContext.getBean("emp3", Employee.class);emp3.work();logger.info("emp3" + emp3);
}/*Employee working
Department name
[2023-06-23 12:02:44:654] [INFO] - TestBeanById.testObj3(TestBeanById.java:118) - emp3Employee{eName='khan', age=23, dept=Department{dname='研发科'}}*/

为数组类型属性赋值

1、编写实体类
public class Person {private String[] hobby;public String[] getHobby() {return hobby;}public void setHobby(String[] hobby) {this.hobby = hobby;}@Overridepublic String toString() {return "Person{" +"hobby=" + Arrays.toString(hobby) +'}';}
}
2、编写配置文件
 <!--注入数组类型的属性-->
<bean id="person" class="com.louis.di_array.Person"><!--注入数组类型属性值--><property name="hobby"><array><value>eat</value><value>sleep</value><value>code</value></array></property>
</bean>
3、测试
@Test
public void testArray(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean-diarray.xml");Person person = applicationContext.getBean("person", Person.class);logger.info("person" + person);
}/*[2023-06-23 12:14:00:835] [INFO] - TestBeanById.testArray(TestBeanById.java:129) - personPerson{hobby=[eat, sleep, code]}*/

为集合类型属性赋值

(一)为list集合类型属性赋值
1、编写实体类并生成set方法

Department

public class Department {private String dname;private List<Employee> empList;public List<Employee> getEmpList() {return empList;}public void setEmpList(List<Employee> empList) {this.empList = empList;}public String getDname() {return dname;}public void setDname(String dname) {this.dname = dname;}public void info(){System.out.println("Department name");}@Overridepublic String toString() {return "Department{" +"dname='" + dname + '\'' +", empList=" + empList +'}';}
}

Employee

public class Employee {private String eName;private Integer age;private Department dept;public String geteName() {return eName;}public void seteName(String eName) {this.eName = eName;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Department getDept() {return dept;}public void setDept(Department dept) {this.dept = dept;}public void work(){System.out.println("Employee working");dept.info();}@Overridepublic String toString() {return "Employee{" +"eName='" + eName + '\'' +", age=" + age +", dept=" + dept +'}';}
}
2、编写配置文件
<!--实现list集合注入-->
<bean id="emp" class="com.louis.di_test.Employee"><property name="eName" value="Louis"></property><property name="age" value="23"></property>
</bean>
<bean id="empTwo" class="com.louis.di_test.Employee"><property name="eName" value="Alex"></property><property name="age" value="22"></property>
</bean>
<bean id="dept" class="com.louis.di_test.Department"><property name="dname" value="研发科"></property><property name="empList"><list>
<!--如果是字符串和基本数据类型,可以直接使用<value>标签--><ref bean="emp"></ref><ref bean="empTwo"></ref></list></property>
</bean>
3、测试
@Test
public void testList(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean-dilist.xml");Department dept = applicationContext.getBean("dept", Department.class);dept.info();logger.info("dept" + dept);
}/*Department name
employee.geteName() = Louis
employee.geteName() = Alex
[2023-06-23 12:31:05:121] [INFO] - TestBeanById.testList(TestBeanById.java:139) - deptDepartment{dname='研发科', empList=[Employee{eName='Louis', age=23, dept=null}, Employee{eName='Alex', age=22, dept=null}]}
*/
(二)为Map集合属性注入值
1、编写实体类并生成set方法

Student

public class Student {private String sname;private String sid;//一个学生可能对应多个老师private Map<String, Teacher> teacherMap;public Map<String, Teacher> getTeacherMap() {return teacherMap;}public void setTeacherMap(Map<String, Teacher> teacherMap) {this.teacherMap = teacherMap;}public String getSname() {return sname;}public void setSname(String sname) {this.sname = sname;}public String getSid() {return sid;}public void setSid(String sid) {this.sid = sid;}public void learn(){System.out.println("学生姓名" + sname + "----" + "学号" + sid);System.out.println(teacherMap);}@Overridepublic String toString() {return "Student{" +"sname='" + sname + '\'' +", sid='" + sid + '\'' +", teacherMap=" + teacherMap +'}';}
}

Teacher

public class Teacher {private String tname;private String tid;public String getTname() {return tname;}public void setTname(String tname) {this.tname = tname;}public String getTid() {return tid;}public void setTid(String tid) {this.tid = tid;}@Overridepublic String toString() {return "Teacher{" +"tname='" + tname + '\'' +", tid='" + tid + '\'' +'}';}
}
2、编写配置文件
    <!--1、创建两个对象2、注入普通类型属性3、在学生bean注入map集合类型属性-->
<bean id="teacher" class="com.louis.di_map.Teacher"><property name="tid" value="110"></property><property name="tname" value="Alex"></property>
</bean>
<bean id="teacher2" class="com.louis.di_map.Teacher"><property name="tid" value="120"></property><property name="tname" value="Khan"></property>
</bean>
<bean id="student" class="com.louis.di_map.Student"><property name="sid" value="18162004"></property><property name="sname" value="Louie"></property><property name="teacherMap"><map><entry><key><value>key1</value></key><ref bean="teacher"></ref></entry><entry><key><value>key2</value></key><ref bean="teacher2"></ref></entry></map></property>
</bean>
3、测试
@Test
public void testMap(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean-diMap.xml");Student student = applicationContext.getBean("student", Student.class);logger.info("student" + student);student.learn();
}/*[2023-06-23 12:57:29:327] [INFO] - TestBeanById.testMap(TestBeanById.java:152) - studentStudent{sname='Louie', sid='18162004', teacherMap={key1=Teacher{tname='Alex', tid='110'}, key2=Teacher{tname='Khan', tid='120'}}}
学生姓名Louie----学号18162004
{key1=Teacher{tname='Alex', tid='110'}, key2=Teacher{tname='Khan', tid='120'}}*/
引用集合类型的bean

将list和map的实现方式换一种写法。

1、在原有的Student和Teacher的基础上,再添加一个Lesson类
public class Lesson {private String lessonName;public String getLessonName() {return lessonName;}public void setLessonName(String lessonName) {this.lessonName = lessonName;}@Overridepublic String toString() {return "Lesson{" +"lessonName='" + lessonName + '\'' +'}';}
}
2、再Student类中添加课程列表
List<Lesson> list;public List<Lesson> getList() {return list;
}public void setList(List<Lesson> list) {this.list = list;
}
3、编写配置文件

加上util的命名空间引入

<?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:util="http://www.springframework.org/schema/util"xsi:schemaLocation="http://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util.xsdhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!--1、创建三个对象2、注入普通类型属性3、使用util:类型 定义。需要更改命名空间引入4、在学生bean引入util:类型定义bean,完成list、map类型注入--><bean id="lessonOne" class="com.louis.di_map.Lesson"><property name="lessonName" value="JAVA开发"></property></bean><bean id="lessonTwo" class="com.louis.di_map.Lesson"><property name="lessonName" value="Python 开发"></property></bean><bean id="teacherOne" class="com.louis.di_map.Teacher"><property name="tname" value="Louie"></property><property name="tid" value="11011"></property></bean><bean id="teacherTwo" class="com.louis.di_map.Teacher"><property name="tname" value="Alex"></property><property name="tid" value="12012"></property></bean><bean id="student" class="com.louis.di_map.Student"><property name="sname" value="khan"></property><property name="sid" value="201811011"></property><!--注入list、map类型的属性--><property name="list" ref="lessonList"></property><property name="teacherMap" ref="teacherMap"></property></bean><util:list id="lessonList"><ref bean="lessonOne"></ref><ref bean="lessonTwo"></ref></util:list><util:map id="teacherMap"><entry><key><value>111</value></key><ref bean="teacherOne"></ref></entry><entry><key><value>222</value></key><ref bean="teacherTwo"></ref></entry></util:map>
</beans>
4、测试
@Test
public void testUtil(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean-diRef.xml");Student student = applicationContext.getBean("student", Student.class);student.learn();logger.info("student" + student);
}/*学生姓名khan----学号201811011
{111=Teacher{tname='Louie', tid='11011'}, 222=Teacher{tname='Alex', tid='12012'}}
[2023-06-23 14:28:04:062] [INFO] - TestBeanById.testUtil(TestBeanById.java:164) - studentStudent{sname='khan', sid='201811011', teacherMap={111=Teacher{tname='Louie', tid='11011'}, 222=Teacher{tname='Alex', tid='12012'}}, list=[Lesson{lessonName='JAVA开发'}, Lesson{lessonName='Python 开发'}]}
*/
p命名空间

命名空间:为避免命名时冲突,再命名后面加上:重命名的方式

xmlns:p = "http://www.springframework.org/schema/p"
编写配置文件
<!--p命名空间注入-->
<bean id="studentP" class="com.louis.di_map.Student" p:sid="201811" p:sname="Louis" p:list-ref="lessonList" p:teacherMap-ref="teacherMap">
</bean>
<util:list id="lessonList"><ref bean="lessonOne"></ref><ref bean="lessonTwo"></ref>
</util:list>
<util:map id="teacherMap"><entry><key><value>111</value></key><ref bean="teacherOne"></ref></entry><entry><key><value>222</value></key><ref bean="teacherTwo"></ref></entry>
</util:map>
测试
@Test
public void testP(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean-diRef.xml");Student studentP = applicationContext.getBean("studentP", Student.class);studentP.learn();logger.info("studentP" + studentP);
}/*学生姓名Louis----学号201811
{111=Teacher{tname='Louie', tid='11011'}, 222=Teacher{tname='Alex', tid='12012'}}
[2023-06-23 14:43:14:562] [INFO] - TestBeanById.testP(TestBeanById.java:176) - studentPStudent{sname='Louis', sid='201811', teacherMap={111=Teacher{tname='Louie', tid='11011'}, 222=Teacher{tname='Alex', tid='12012'}}, list=[Lesson{lessonName='JAVA开发'}, Lesson{lessonName='Python 开发'}]}
*/

引入外部属性文件

应用场景:在一个文件中如果出现多个bean的创建和注入,维护就会比较困难。可以将一些特定的文件放在特定位置在spring中进行引入,如数据库文件。

实现步骤(数据库的配置文件引入)

1、引入相关依赖
 <dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.16</version>
</dependency>
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-dbutils/commons-dbutils -->
<dependency><groupId>commons-dbutils</groupId><artifactId>commons-dbutils</artifactId><version>1.7</version>
</dependency>
2、创建Dbutils.properties
username=root
password=root
url=jdbc:mysql://localhost:3306/spring
driver=com.mysql.cj.jdbc.Driver
3、创建spring的配置文件

引入context命名空间,引入属性文件,使用表达式完成注入。

context命名空间

xmlns:contex="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"

引入属性文件

<!--引入外部属性文件-->
<contex:property-placeholder location="classpath:Dbutils.properties"></contex:property-placeholder>

完整配置

<?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:contex="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!--引入外部属性文件--><contex:property-placeholder location="classpath:Dbutils.properties"></contex:property-placeholder>
<!--完成数据库信息注入--><bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="url" value="${url}"></property><property name="username" value="${username}"></property><property name="password" value="${password}"></property><property name="driver" value="${driver}"></property></bean>
</beans>
4、测试
@Test
public void testDbutils(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean-Dbutils.xml");DruidDataSource dataSource = applicationContext.getBean("druidDataSource", DruidDataSource.class);logger.info("dataSource" + dataSource);
}
/*
* [2023-06-23 15:36:52:008] [INFO] - TestBeanById.testDbutils(TestBeanById.java:189) - dataSource{CreateTime:"2023-06-23 15:36:51",ActiveCount:0,PoolingCount:0,CreateCount:0,DestroyCount:0,CloseCount:0,ConnectCount:0,Connections:[]
}
* */

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/4946.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

零基础学习,轻松打造物业服务小程序

现如今&#xff0c;物业服务已经成为了人们生活中不可或缺的一部分。为了更好地满足人们对物业服务的需求&#xff0c;许多企业和个人开始开发物业服务小程序&#xff0c;以便提供更加便捷和高效的服务。然而&#xff0c;对于大多数人来说&#xff0c;搭建一个小程序可能需要一…

智能ai绘画软件帮你用科技点亮创意火花

李明&#xff1a;嘿&#xff0c;你听说过ai绘画软件吗&#xff1f;我最近对数字艺术产生了浓厚的兴趣 王磊&#xff1a;当然&#xff01;ai绘画软件真是太神奇了&#xff01;它可以将抽象的文字描述转换成惊人的艺术作品。 李明&#xff1a;是吗&#xff1f;它们绘制的效果怎…

数据库及数据表的相关操作(一)

目录 概念知识一、管理逻辑库与数据表二、常用数据类型和约束2.1 数字数据类型2.2 字符串数据类型2.3 日期数据类型2.4 字段约束 三、索引运行机制和使用原则3.1 创建索引3.2 添加与删除索引3.3 索引的使用原则 概念知识 关系型数据库&#xff1a; 使用了关系模型的数据库系统&…

深度学习——CNN卷积神经网络

基本概念 概述 卷积神经网络&#xff08;Convolutional Neural Network&#xff0c;CNN&#xff09;是一种深度学习中常用于处理具有网格结构数据的神经网络模型。它在计算机视觉领域广泛应用于图像分类、目标检测、图像生成等任务。 核心思想 CNN 的核心思想是通过利用局部…

Linux内核源代码的目录结构包括部分:

内核核心代码&#xff1a;这部分代码包括内核的各个子系统和模块&#xff0c;如进程管理、内存管理、文件系统、网络协议栈等。这些代码构成了Linux内核的核心功能。 非核心代码&#xff1a;除了核心代码之外&#xff0c;还包括一些非核心的代码和文件&#xff0c;如库文件、固…

和chatgpt学架构03-引入UI框架(elment-plus)

目录 1 项目目录及文件的具体作用1.1 App.vue1.2 main.js的作用1.3 main.js什么时候被调用1.4 npm run serve干了什么事情1.5 package.json的作用 2 安装UI框架2.1 安装命令2.2 全局引入 3 启动工程总结 我们已经安装好了我们的vue脚手架&#xff0c;用vscode打开工程目录 要自…

【FPGA】基于C5的第一个SoC工程

文章目录 前言SoC的Linux系统搭建 前言 本文是在毕业实习期间学习FPGA的SoC开发板运行全连接神经网络实例手写体的总结。 声明&#xff1a;本文仅作记录和操作指南&#xff0c;涉及到的操作会尽量细致&#xff0c;但是由于文件过大不会分享文件&#xff0c;具体软件可以自行搜…

Leetcode-每日一题【109.有序链表转换二叉搜索树】

题目 给定一个单链表的头节点 head &#xff0c;其中的元素 按升序排序 &#xff0c;将其转换为高度平衡的二叉搜索树。 本题中&#xff0c;一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差不超过 1。 示例 1: 输入: head [-10,-3,0,5,9]输出: [0,-3,9,-…

VS报错E1696 无法打开类似于stdio.h等头文件的解决办法

VS报错E1696 无法打开类似于stdio.h等头文件的解决办法 我的VS版本是2022的&#xff0c;然后我今天把同事在VS2017上的code&#xff08;一个完整的解决方案&#xff09;从svn上拿过来。结果发现&#xff0c;一大堆E1696的错误。主要表现就是项目中include的一些常用的c语言基础…

算法竞赛字符串常用操作大全

算法竞赛字符串常用操作总结来啦~ &#x1f44a; 大家好 我是寸铁&#x1f4aa; 考前需要刷大量真题,大家一起相互监督&#xff0c;每日做N题&#xff0c;一起上岸吧✌️ ~ 冲刺蓝桥杯省一模板大全来啦 &#x1f4a5; ~ 蓝桥杯4月8号就要开始了 &#x1f64f; ~ 还没背熟模…

字幕切分视频

Whisper 仓库地址&#xff1a; https://github.com/openai/whisper 可用模型信息&#xff1a; 测试视频&#xff1a;18段&#xff0c;总共447S视频&#xff08;11段前&#xff1a;有11段开头有停顿的视频&#xff09; Tiny: 跑完&#xff1a;142S &#xff0c;11段前&#xf…

(栈队列堆) 剑指 Offer 09. 用两个栈实现队列 ——【Leetcode每日一题】

❓ 剑指 Offer 09. 用两个栈实现队列 难度&#xff1a;简单 用两个栈实现一个队列。队列的声明如下&#xff0c;请实现它的两个函数 appendTail 和 deleteHead &#xff0c;分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素&#xff0c;deleteHead …

vscode远程连接提示:过程试图写入的管道不存在(删除C:\Users\<用户名>\.ssh\known_hosts然后重新连接)

文章目录 复现过程原因解决方法总结 复现过程 我是在windows上用vscode远程连接到我的ubuntu虚拟机上&#xff0c;后来我的虚拟机出了点问题&#xff0c;我把它回退了&#xff0c;然后再连接就出现了这个问题 原因 本地的known_hosts文件记录服务器信息与现服务器的信息冲突了…

虚拟机挂载USB设备/USB serial 连接开发板

虚拟机挂载USB设备 1、添加USB设备 2、终端输入&#xff1a;sudo fdisk -l 查看Device设备&#xff1a; 3、创建挂载目录&#xff1a;mkdir /mnt/usb 4、执行挂载命令&#xff1a;sudo mount /dev/sdb1 /mnt/usb ,查看/mnt/usb目录下是否存在U盘中的数据&#xff1a; 5、用…

设计模式——桥梁模式

桥梁模式 定义 桥梁模式&#xff08;Bridge Pattern&#xff09;也叫做桥接模式。 将抽象和显示解耦&#xff0c;使得两者可以独立地变化。 优缺点、应用场景 优点 抽象和实现的解耦。 这是桥梁模式的主要特点&#xff0c;它完全是为了解决继承的缺点而提出的设计模式。优…

成为一个年薪30W+的DFT工程师是一种什么体验?

一直以来&#xff0c;DFT都是数字IC设计行业中相对神秘的一个岗位。 你说他重要吧&#xff0c;并不是所有芯片设计公司都有这个岗位&#xff0c;你说他不重要吧&#xff0c;但凡芯片产品达到一定规模后&#xff0c;就必须设置DFT部门。 一、什么是DFT&#xff1f; DFT&#x…

原生信息流广告APP应用内增收及计费模式

比起传统的广告宣传&#xff0c;信息流最大的优势就在于流量的庞大。与此同时&#xff0c;多样化的信息流广告形式和精准的定向&#xff0c;还可以帮助广告主准确获取意向流量。此外&#xff0c;它的广告形式不强迫推送&#xff0c;因此也受到了广泛用户的支持和青睐。 原生信…

音视频开发实战03-FFmpeg命令行工具移植

一&#xff0c;背景 作为一个音视频开发者&#xff0c;在日常工作中经常会使用ffmpeg 命令来做很多事比如转码ffmpeg -y -i test.mov -g 150 -s 1280x720 -codec libx265 -r 25 test_h265.mp4 &#xff0c;水平翻转视频&#xff1a;ffmpeg -i src.mp4 -vf hflip -acodec copy …

26.JavaWeb-SpringSecurity安全框架

1.SpringSecurity安全框架 Spring Security是一个功能强大且灵活的安全框架&#xff0c;它专注于为Java应用程序提供身份验证&#xff08;Authentication&#xff09;、授权&#xff08;Authorization&#xff09;和其他安全功能。Spring Security可以轻松地集成到Spring框架中…

MySQL数据库(五)

目录 一、数据库的约束 1.1 约束类型 1.1.1 null约束 1.1.2unique约束 1.1.3default默认值约束 1.1.4primary key主键约束 1.1.5foreign key外键约束 二、内容重点总结 一、数据库的约束 1.1 约束类型 not null - 指示某列不能存储 null值。unique - 保证某列的每行必须有唯一…