spring5(三):IOC操作Bean管理(基于xml方式)
IOC操作Bean管理(基于xml方式)
- 前言
- 一、基于 xml 方式创建对象
- 二、基于 xml 方式注入属性
- 1. 使用 set 方法进行属性注入
- 2. 使用有参数构造进行属性注入
- 3. p 名称空间注入简化操作(了解)
- 三、xml 注入其它类型属性
- 1. 字面量
- 2. 注入属性-外部 bean
- 3. 注入属性-内部 bean
- 4. 注入属性-级联赋值
- 四、xml 注入集合属性
- 1. 注入数组类型属性
- 2. 注入 List 集合类型属性
- 3. 注入 Map 集合类型属性
- 4. 在集合里面设置对象类型值
- 5. 把集合注入部分提取出来
- 五、bean作用域
- 六、bean 生命周期
- 七、xml 自动装配
- 八、外部属性文件
- 九、FactoryBean
前言
本博主将用CSDN记录软件开发求学之路上亲身所得与所学的心得与知识,有兴趣的小伙伴可以关注博主!也许一个人独行,可以走的很快,但是一群人结伴而行,才能走的更远!让我们在成长的道路上互相学习,欢迎关注!
一、基于 xml 方式创建对象
⭕在
spring
配置文件中,使用bean
标签,标签里面添加对应属性,就可以实现对象创建
⭕在
bean
标签有很多属性,介绍常用的属性
id
属性:唯一标识class
属性:类全路径(包类路径)name
属性:作用与id
属性一致,区别是name
属性里面可以用特殊字符,但现在很少用name
属性了
⭕创建对象时候,默认也是执行无参数构造方法完成对象创建,如果在类里用有参构造器覆盖无参构造器,运行时则会报错。
二、基于 xml 方式注入属性
DI:依赖注入,就是注入属性
1. 使用 set 方法进行属性注入
① 创建类,定义属性和对应的 set 方法
//演示使用 set 方法进行注入属性
public class Person {private String name;private String food;public void setName(String name) {this.name = name;}public void setFood(String food) {this.food = food;}public void eat(){System.out.println(this.name+"吃"+this.food);}}
② 在 spring 配置文件配置对象创建,配置属性注入
<!--配置 Person 对象创建--><bean id="person_ir" class="com.ir.spring5.Person"><!--使用 property 完成属性注入name:类里面属性名称value:向属性注入的值--><property name="name" value="小老师ir"></property><property name="food" value="java"></property></bean>
property标签中的属性name是相应的类中的属性名,value是指要赋予属性的值
③ 测试代码:
@Test public void testEat(){ //1.加载spring配置文件 ApplicationContext context = new ClassPathXmlApplicationContext("person1.xml"); //2. 获取配置创建的对象 Person person = context.getBean("person_ir",Person.class); //3. 测试 System.out.println(person);//com.ir.spring5.Person@1b26f7b2 person.eat(); //[小老师ir]吃java }
2. 使用有参数构造进行属性注入
① 创建类,定义属性,创建属性对应有参数构造方法
package com.ir.spring5;public class Car {private String number;private String speed;public Car(String number, String speed) {this.number = number;this.speed = speed;}public void run(){System.out.println(number+"::"+speed);}
}
② 在 spring 配置文件中进行配置
<!--配置 Car 对象创建--><bean id="car_ir" class="com.ir.spring5.Car"><!--有参数构造注入属性--><!--方式1:通过name属性来确定类中的属性名--><constructor-arg name="number" value="01"></constructor-arg><constructor-arg name="speed" value="200"></constructor-arg><!--方式2:通过索引来确定属性名-->
<!-- <constructor-arg index="0" value="01"></constructor-arg>-->
<!-- <constructor-arg index="1" value="200"></constructor-arg>--></bean>
测试:
@Test public void testCar(){ //1.加载配置文件 ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml"); //2.获取配置文件创建的对象 Car car = context.getBean("car_ir",Car.class); //3.测试 System.out.println(car);//com.ir.spring5.Car@a74868d car.run();//01::200 }
3. p 名称空间注入简化操作(了解)
使用 p 名称空间注入,可以简化基于 xml 配置方式
① 添加 p 名称空间在配置文件中
② 进行属性注入,在 bean 标签里面进行操作
<bean id="person_ir" class="com.ir.spring5.Person" p:name="小老师ir" p:food="c++">
</bean>
三、xml 注入其它类型属性
1. 字面量
⭕ null 值
<bean id="person_ir" class="com.ir.spring5.Person"><property name="name" ><null/></property><property name="food" value="java"></property></bean>
@Test
public void testEat(){ ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml"); Person person = context.getBean("person_ir",Person.class); System.out.println(person);//com.ir.spring5.Person@1b26f7b2 person.eat(); //[null]吃java
⭕ 属性值包含特殊符号
● 方法一:把<>进行转义
<
>
<bean id="person_ir" class="com.ir.spring5.Person"><property name="name" value="<小老师ir>"></property><property name="food" value="java"></property></bean>
@Test
public void testEat(){ ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml"); Person person = context.getBean("person_ir",Person.class); System.out.println(person);//com.ir.spring5.Person@a74868d person.eat(); //<小老师ir>吃java
● 方法二:把带特殊符号内容写到 CDATA
<bean id="person_ir" class="com.ir.spring5.Person"><property name="name" ><value><![CDATA[<<小老师ir>>]]></value></property><property name="food" value="java"></property></bean>
@Test
public void testEat(){ //1.加载spring配置文件 ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");//2. 获取配置创建的对象 Person person = context.getBean("person_ir",Person.class); //3. 测试 System.out.println(person);//com.ir.spring5.Person@a74868d person.eat(); //[<<小老师ir>>]吃java
2. 注入属性-外部 bean
演示步骤:
① 创建两个类 service 类和 dao 类
② 在 service 调用 dao 里面的方法
UserDao
package Dao;/*** @author shkstart* @create 2022-05-07 23:08*/
public interface UserDao {public void update();
}
UserService
package Service;import Dao.UserDao;/*** @author shkstart* @create 2022-05-07 23:08*/
public class UserService {//创建 UserDao 类型属性,生成 set 方法private UserDao userDao;public void setUserDao(UserDao userDao) {this.userDao = userDao;}public void add() {System.out.println("service add...............");userDao.update();}
}
UserDaoImpl
package Dao;/*** @author shkstart* @create 2022-05-07 23:08*/
public class UserDaoImpl implements UserDao{@Overridepublic void update() {System.out.println("dao update...........");}
}
③ 在 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:util="http://www.springframework.org/schema/util"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd"><!--创建 UserService 对象--><bean id="userservice" class="Service.UserService"><!--注入 userDao 对象name 属性:类里面属性名称ref 属性:创建 userDao 对象 bean 标签 id 值--><property name="userDao" ref="userdaoimpl"></property></bean><!--创建 UserDaoImpl 对象--><bean id="userdaoimpl" class="Dao.UserDaoImpl"></bean></beans>
测试:
@Testpublic void testBean(){ApplicationContext context1 = new ClassPathXmlApplicationContext("bean2.xml");UserService userService = (UserService)context1.getBean("userservice");System.out.println(userService);//Service.UserService@eafc191userService.add();
// service add...............
// dao update...........}
3. 注入属性-内部 bean
① 一对多关系:部门和员工,一个部门有多个员工,一个员工属于一个部门,部门是一,员工是多
② 在实体类之间表示一对多关系,员工表示所属部门,使用对象类型属性进行表示
部门类
package Bean;
public class Dept {private String dname;public void setDname(String dname) {this.dname = dname;}@Overridepublic String toString() {return "Dept{" +"dname='" + dname + '\'' +'}';}
}
员工类
package Bean;public class Emp {private String ename;private String gender;//员工属于某一个部门,使用对象形式表示private Dept dept;public void setDept(Dept dept) {this.dept = dept;}public void setEname(String ename) {this.ename = ename;}public void setGender(String gender) {this.gender = gender;}public void add() {System.out.println(ename+"::"+gender+"::"+dept);}
}
③ 在 spring 配置文件中进行配置
<!--内部bean--><bean id="emp" class="Bean.Emp"><!--设置两个属性--><property name="ename" value="小老师ir"></property><property name="gender" value="女"></property><!--设置对象类型属性--><property name="dept"><bean id="dept" class="Bean.Dept"><property name="dname" value="安保部"></property></bean></property></bean>
测试
@Testpublic void testEmp(){ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");Emp emp = (Emp)context.getBean("emp");System.out.println(emp);//Bean.Emp@69b0fd6femp.add();//小老师ir::女::Dept{dname='安保部'}}
4. 注入属性-级联赋值
方式一:
在 spring 配置文件
bean4.xml
中进行配置
<!--级联赋值--><bean id="emp" class="Bean.Emp"><!--设置两个普通属性--><property name="ename" value="小老师ir"></property><property name="gender" value="女"></property><!--级联赋值--><property name="dept" ref="dept"></property></bean><bean id="dept" class="Bean.Dept"><property name="dname" value="技术部"></property></bean>
测试:
@Testpublic void testEmp2(){ApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");Emp emp = (Emp)context.getBean("emp");System.out.println(emp);//Bean.Emp@462d5aeeemp.add();//小老师ir::女::Dept{dname='技术部'}}
方式二:员工属于某一个部门,使用对象形式表示
<!--级联赋值--><bean id="emp" class="Bean.Emp"><!--设置两个普通属性--><property name="ename" value="小老师ir"></property><property name="gender" value="女"></property><!--级联赋值--><property name="dept" ref="dept"></property><property name="dept.dname" value="技术部"></property></bean><bean id="dept" class="Bean.Dept"></bean>
测试:
@Testpublic void testEmp3(){ApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");Emp emp = (Emp)context.getBean("emp");System.out.println(emp);//Bean.Emp@757942a1emp.add();//小老师ir::女::Dept{dname='技术部'}}
注意:此种方法中,
Emp
类中必须有getDept( )
方法
四、xml 注入集合属性
1. 注入数组类型属性
2. 注入 List 集合类型属性
3. 注入 Map 集合类型属性
步骤:
① 创建类,定义数组、list、map、set 类型属性,生成对应 set 方法
Stu类
public class Stu {//1 数组类型属性private String[] courses;//2 list集合类型属性private List<String> list;//3 map集合类型属性private Map<String,String> maps;//4 set集合类型属性private Set<String> sets;public void setSets(Set<String> sets) {this.sets = sets;}public void setCourses(String[] courses) {this.courses = courses;}public void setList(List<String> list) {this.list = list;}public void setMaps(Map<String, String> maps) {this.maps = maps;}@Overridepublic String toString() {return "Stu{" +"courses=" + Arrays.toString(courses) +", list=" + list +", maps=" + maps +", sets=" + sets + '}';}
}
② 在 spring 配置文件进行配置
<bean id="student" class="collectiontest.Stu"> <!--注入数组属性--><property name="courses"><array ><value>Java</value><value>C++</value></array></property><!--注入list属性--><property name="list"><list><value>Python</value><value>Go</value></list></property><!--注入map属性--><property name="maps"><map><entry key="小老师ir" value="Java"></entry><entry key="小老师ir" value="C++"></entry></map></property><!--注入set属性--><property name="sets"><set><value>喜羊羊</value><value>美羊羊</value></set></property></bean>
测试:
@Testpublic void test(){ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");Stu student = context.getBean("student",Stu.class);System.out.println(student);//Stu{courses=[Java, C++], list=[Python, Go], maps={小老师ir=C++}, sets=[喜羊羊, 美羊羊]}}
4. 在集合里面设置对象类型值
Stu类
public class Stu {//1 数组类型属性private String[] courses;//2 list集合类型属性private List<String> list;//3 map集合类型属性private Map<String,String> maps;//4 set集合类型属性private Set<String> sets;//学生所学多门课程private List<Course> courseList;public void setCourseList(List<Course> courseList) {this.courseList = courseList;}public void setSets(Set<String> sets) {this.sets = sets;}public void setCourses(String[] courses) {this.courses = courses;}public void setList(List<String> list) {this.list = list;}public void setMaps(Map<String, String> maps) {this.maps = maps;}@Overridepublic String toString() {return "Stu{" +"courses=" + Arrays.toString(courses) +", list=" + list +", maps=" + maps +", sets=" + sets +", courseList=" + courseList +'}';}
}
Course类
//课程类
public class Course {private String cname; //课程名称public void setCname(String cname) {this.cname = cname;}@Overridepublic String toString() {return "Course{" +"cname='" + cname + '\'' +'}';}
}
在 spring 配置文件进行配置
<!--创建多个 course 对象--><bean id="course1" class="collectiontest.Course"><property name="cname" value="英语课"></property></bean><bean id="course2" class="collectiontest.Course"><property name="cname" value="语文课"></property></bean><bean id="course3" class="collectiontest.Course"><property name="cname" value="数学课"></property></bean><!--创建Stu对象--><bean id="student1" class="collectiontest.Stu"><!--注入 list 集合类型,值是对象--><property name="courseList"><list><ref bean="course1"></ref><ref bean="course2"></ref><ref bean="course3"></ref></list></property></bean>
测试
@Testpublic void test(){ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");Stu student = context.getBean("student1",Stu.class);System.out.println(student);//Stu{courses=null, list=null, maps=null, sets=null, courseList=[Course{cname='英语课'}, Course{cname='语文课'}, Course{cname='数学课'}]}}
5. 把集合注入部分提取出来
Book类·
public class Book {private List<String> list;public void setList(List<String> list) {this.list = list;}@Overridepublic String toString() {return "Book{" +"list=" + list +'}';}
}
步骤:
① 在 spring 配置文件中引入名称空间 util
② 在 spring 配置文件进行配置,使用 util 标签完成 list 集合注入提取
<!--1 提取list集合类型属性注入--><util:list id="bookList"><value>java</value><value>c++</value><value>python</value></util:list><!--2 提取list集合类型属性注入使用--><bean id="book" class="collectiontest.Book" scope="prototype"><property name="list" ref="bookList"></property></bean>
测试
@Testpublic void test(){ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");Book book= context.getBean("book", Book.class);System.out.println(book);//Book{list=[java, c++, python]}}
五、bean作用域
⭕ 在 Spring 里面,设置创建 bean 实例是单实例还是多实例 ?
⭕在 Spring 里面,默认情况下,bean 是单实例对象
Book类
public class Book {private List<String> list;public void setList(List<String> list) {this.list = list;}
}
在 spring 配置文件进行配置
<!--1 提取list集合类型属性注入--><util:list id="bookList"><value>java</value><value>c++</value><value>python</value></util:list><!--2 提取list集合类型属性注入使用--><bean id="book" class="collectiontest.Book" ><property name="list" ref="bookList"></property></bean>
测试:
@Testpublic void test(){ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");Book book1= context.getBean("book", Book.class);Book book2= context.getBean("book", Book.class);System.out.println(book1);//collectiontest.Book@27d415d9System.out.println(book2);//collectiontest.Book@27d415d9}
由以上测试输出结果可知,创建的两个book对象地址相同,即为其实是同一个对象
⭕如何设置单实例还是多实例
● 在 spring 配置文件 bean 标签里面有属性(scope)用于设置单实例还是多实例
● scope 属性值,其中有两个常见的词
- 第一个值,默认值,singleton,表示是单实例对象
- 第二个值prototype,表示是多实例对象 Book类与如上相同
在 spring 配置文件进行配置
<!--1 提取list集合类型属性注入--><util:list id="bookList"><value>java</value><value>c++</value><value>python</value></util:list><!--2 提取list集合类型属性注入使用--><bean id="book" class="collectiontest.Book" scope="prototype"><property name="list" ref="bookList"></property>y</bean>
测试:
@Testpublic void test(){ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");Book book1= context.getBean("book", Book.class);Book book2= context.getBean("book", Book.class);System.out.println(book1);//collectiontest.Book@27d415d9System.out.println(book2);//collectiontest.Book@5c18298f}
由以上测试输出结果可知,创建的两个book对象地址不相同,即为是两个对象
⭕ singleton 和 prototype 区别
● singleton 单实例,prototype 多实例
● 设置 scope 值是 singleton 时候,加载 spring 配置文件时候就会创建单实例对象
● 设置 scope 值是 prototype 时候,不是在加载 spring 配置文件时候创建 对象,而是在调用getBean 方法时候创建多实例对象
六、bean 生命周期
⭕ 生命周期:从对象创建到对象销毁的过程
⭕ bean 生命周期
(1)通过构造器创建 bean 实例(无参数构造)
(2)为 bean 的属性设置值和对其他 bean 引用(调用set 方法)
(3)调用 bean 的初始化的方法(需要进行配置初始化的方法)
(4)bean 可以使用了(对象获取到了)
(5)当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)
⭕ 演示 bean 生命周期
Order类
public class Order {private String name;public Order() {System.out.println("第一步:执行无参构造器创建对象");}public void setName(String name) {this.name = name;System.out.println("第二步:调用set()方法设置属性值");}public void initMethod(){System.out.println("第三步:执行初始化方法");}public void destroyMethod(){System.out.println("第五步:执行销毁的方法");}}
在 spring 配置文件进行配置
<bean id="order" class="collectiontest.Order" init-method="initMethod" destroy-method="destroyMethod"><property name="name" value="电脑订单"></property>
</bean>
测试:
@Testpublic void test(){ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");Order order= context.getBean("order", Order.class);System.out.println("第四步:获取创建 bean 实例对象");System.out.println(order);context.close();
// 第一步:执行无参构造器创建对象
// 第二步:调用set()方法设置属性值
// 第三步:执行初始化方法
// 第四步:获取创建 bean 实例对象
// collectiontest.Order@4a87761d
// 第五步:执行销毁的方法}
⭕ bean 的后置处理器,bean 生命周期有七步
(1)通过构造器创建 bean 实例(无参数构造)
(2)为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
(3)把bean 实例传递 bean 后置处理器的方法 postProcessBeforeInitialization
(4)调用 bean 的初始化的方法(需要进行配置初始化的方法)
(5)把 bean 实例传递 bean 后置处理器的方法postProcessAfterInitialization
(6)bean 可以使用了(对象获取到了)
(7)当容器关闭时候,调用bean 的销毁的方法(需要进行配置销毁的方法)
⭕ 演示添加后置处理器效果
(1)创建类,实现接口 BeanPostProcessor,创建后置处理器
public class MyBeanPost implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("在初始化之前执行的方法");return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("在初始化之后执行的方法");return bean;}
}
在 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"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!--配置order对象--><bean id="order" class="bean.Order" init-method="initMethod" destroy-method="destroyMethod"><property name="name" value="电脑订单"></property></bean><!--配置后置处理器--><bean id="mybeanpost" class="bean.MyBeanPost"></bean>
</beans>
测试:
@Testpublic void test(){ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");Order order= context.getBean("order", Order.class);System.out.println("第四步:获取对象");System.out.println(order);context.close();
// 第一步:执行无参构造器创建对象
// 第二步:调用set()方法设置属性值
// 在初始化之前执行的方法
// 第三步:执行初始化方法
// 在初始化之后执行的方法
// 第四步:获取对象
// bean.Order@37374a5e
// 第五步:执行销毁的方法}
七、xml 自动装配
⭕ 什么是自动装配?
根据指定装配规则(属性名称或者属性类型),Spring 自动将匹配的属性值进行注入
① bean 标签属性 autowire,配置自动装配
② autowire 属性常用两个值:
- byName:根据属性名称注入 ,注入值 bean 的 id 值和类属性名称一样
- byType :根据属性类型注入
⭕演示自动装配过程
● 根据属性名称自动注入
Dept类
public class Dept {private String name;public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Dept{" +"name='" + name + '\'' +'}';}
}
Emp类
public class Emp {private Dept dept;public void setDept(Dept dept) {this.dept = dept;}@Overridepublic String toString() {return "Emp{" +"dept=" + dept +'}';}
}
在 spring 配置文件进行配置
<!--创建emp对象--><!--使用自动装配方式注入属性:通过属性名的方式--><bean id="emp" class="bean.Emp" autowire="byName"><!--使用手动方式注入属性-->
<!-- <property name="dept" ref="dept"></property>--></bean><!--创建dept对象--><bean id="dept" class="bean.Dept"><property name="name" value="技术部"></property></bean>
测试:
@Testpublic void test() {ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean5.xml");Emp emp = context.getBean("emp", Emp.class);System.out.println(emp);//Emp{dept=Dept{name='技术部'}}}
● 根据属性类型自动注入
<!--创建emp对象--><!--使用自动装配方式注入属性:通过属性类型的方式--><bean id="emp" class="bean.Emp" autowire="byType"><!--使用手动方式注入属性-->
<!-- <property name="dept" ref="dept"></property>--></bean><!--创建dept对象--><bean id="dept" class="bean.Dept"><property name="name" value="技术部"></property></bean>
测试:
@Testpublic void test() {ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean5.xml");Emp emp = context.getBean("emp", Emp.class);System.out.println(emp);//Emp{dept=Dept{name='技术部'}}}
注意:通过属性类型的方式自动装配时,同一类型不能有多个bean对象,否则会报错
八、外部属性文件
⭕ 直接配置数据库信息
① 引入德鲁伊连接池依赖 jar 包
② 配置德鲁伊连接池
<!--创建数据库连接池对象--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><!--直接对连接池进行属性配置--><property name="driverClassName" value="com.mysql.jdbc.Driver"></property><property name="url" value="jdbc:mysql://localhost:3306/userDb"></property><property name="username" value="root"></property><property name="password" value="root"></property></bean>
⭕ 引入外部属性文件配置数据库连接池
(1)创建外部属性文件,properties 格式文件,写数据库信息
jdbc.properties
prop.driverClass=com.mysql.jdbc.Driver
prop.url=jdbc:mysql://localhost:3306/userDb
prop.userName=root
prop.password=root
(2)把外部 properties 属性文件引入到 spring 配置文件中
① 引入 context 名称空间
② 在 spring 配置文件使用标签引入外部属性文件
<!--引入外部属性文件--><context:property-placeholder location="classpath:jdbc.properties"/><!--创建数据库连接池对象--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><!--对连接池进行属性配置--><property name="driverClassName" value="com.mysql.jdbc.Driver"></property><property name="url" value="jdbc:mysql://localhost:3306/userDb"></property><property name="username" value="root"></property><property name="password" value="root"></property></bean>
九、FactoryBean
Spring 有两种类型 bean,一种普通 bean,另外一种工厂 bean(FactoryBean)
- 普通 bean:在配置文件中定义 bean 类型就是返回类型
- 工厂 bean:在配置文件定义 bean 类型可以和返回类型不一样
步骤:
① 创建类,让这个类作为工厂 bean,实现接口 FactoryBean
② 实现口里面的方法,在实现的方法中定义返回的bean 类型
Course类
public class Course {private String cname; //课程名称public void setCname(String cname) {this.cname = cname;}public String getCname(){return this.cname;}@Overridepublic String toString() {return "Course{" +"cname='" + cname + '\'' +'}';}
}
public class MyBean implements FactoryBean<Course> {@Overridepublic Course getObject() throws Exception {Course course = new Course();course.setCname("Java");return course;}@Overridepublic Class<?> getObjectType() {return null;}
}
③ 在 spring 配置文件进行配置
<!--创建MyBean对象--><bean id="mybean" class="factorybean.MyBean"></bean>
测试:
@Testpublic void test(){ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");Course course= context.getBean("mybean", Course.class);System.out.println(course.getCname());//Java}
相关文章:
FFMPEG windows版本编译
安装MSYS2: 更新MSYS2系统: pacman -Syu 打开正确的终端:?如果您要编译64位版本的FFmpeg)或MSYS2 MinGW 32-bit(如果您需要编译32位版本)。 安装所需组件:?在打开的MinGW-w64终端中,安装编译FFmpeg所需的工具链、开发工具和依赖库: pacman -S base-devel git mingw-…...
推进 OKR 目标管理落地的最佳实践
企业如何通过 Tita 推进 OKR 目标管理落地?本文将从 OKR 推进落地的四大阶段,来分别为大家介绍企业推进的全流程。这四个阶段分别是:OKR 实施准备阶段 OKR 制定阶段 OKR 执行推阶段 OKR 复盘阶段准备:OKR 实施准备阶段 OKR 实施准备阶段是开始部署和准备落地 OKR 的关键阶段…...
郑州ccpc总结---ly
今年作为大一,第一次参加ccpc的大型比赛,感觉非常不好,感觉没有打出自己该有的水平,我们队很快就写完了签到题,第二题把题的思路写错了,是一道贪心,却写成了dp,导致经历了千辛万苦,最后得到了超时这个结果,最后经过了三个小时,删删改改,才把那道贪心题写完,我自己…...
第二次冲刺9
111...
CentOS配置静态IP
CentOS配置静态IP1.查看虚拟机使用的网络连接方式2.查看虚拟机的网络连接方式IP3.1.CentOS6.8之前IP配置方法 打开系统输入setup,进入文本模式设置工具进入网络配置模式进入网络配置模式过后在进入设置配置,选项eth0网卡进入配置静态IP关闭DHCP,在静态IP,子网掩码和默认网关…...
[20240518]任意进制转换xtoy.sql脚本.txt
[20240518]任意进制转换xtoy.sql脚本.txt--//前几天尝试改进10进制转任意进制,以及其他进制转10进制脚本,有了这两个脚本就可以通过10进制实现任意进制的转换.$ cat 10tox.sqlset term offcolumn 2 new_value 2select null "2" from dual where 1=2;select nvl(&…...
spring5(三):IOC操作Bean管理(基于xml方式)
IOC操作Bean管理(基于xml方式)前言一、基于 xml 方式创建对象二、基于 xml 方式注入属性1. 使用 set 方法进行属性注入2. 使用有参数构造进行属性注入3. p 名称空间注入简化操作(了解)三、xml 注入其它类型属性1. 字面量2. 注入属…...
Vue的快速上手
一、创建一个 Vue 应用 前提条件 熟悉命令行已安装 16.0 或更高版本的 Node.js在本篇中,我们将介绍如何在本地搭建 Vue 单页应用。创建的项目将使用基于 Vite 的构建设置,并允许我们使用 Vue 的单文件组件 (SFC)。 确保你安装了最新版本的 Node.js&…...
通过ELK+kafka采集微服务日志
在springboot微服务中采集日志推送kafka背景整体流程图快速搭建kafkazk开发环境通过logback记录日志到kafka快速搭建ELK环境Kibana查看,统计日志背景 在分布式的项目中,各功能模块产生的日志比较分散,同时为满足性能要求,同一个微…...
开启新航路,拓尔思发力AIGC市场 | 爱分析调研
2022年,随着AI聊天机器人GhatGPT在世界范围内持续火爆,极具创意、表现力、个性化且能快速迭代的AIGC技术成功破圈,成为全民讨论热点。 AIGC是指在确定主题下,由算法模型自动生成内容,包括单模态内容如文本、图像、音频…...
01-死磕QNX someip
1. vsomeip3.1.20版本 环境配置 export COMMONAPI_CONFIG/etc/commonapi.ini export LD_LIBRARY_PATH/sdcard/someip:$LD_LIBRARY_PATH export VSOMEIP_CONFIGURATION/etc/vsomeip-service.json export VSOMEIP_APPLICATION_NAMEHelloWorldSomeIPService sysctl -w net.ine…...
OTFS输入输出关系
目录 1. OTFS输入输出关系的矩阵表示 1.1 OTFS:矩阵表示 1.2 OTFS发射机的实现 1.2.1 传统的OTFS调制 ISFFT 海森堡变换 1.2.2 基于IDZT的OTFS调制 1.3 OTFS接收机的实现 1.3.1 传统的OTFS解调 维格纳变换 SFFT 1.3.2 基于DZT的OTFS解调 Appendix-Matlab C…...
Java的抽象类和接口
目录 一 、抽象类 1、抽象类概念 2、抽象类语法 3、抽象类特性 4、抽象类的作用 二、接口 1、接口的概念 2、语法规则 3、接口使用 4、接口特性 5、实现多个接口 6、接口间的继承 7、抽象类和接口的区别 8、接口使用实例 9、Clonable 接口和深拷贝 三、Object类…...
作为一个女测试员是什么样的体验?
面试时极度紧张,语无伦次,觉得肯定没戏,最后却拿到高薪offer。 工作之后我听同事们讲,测试总监面试官并没打算要我,但身边的人都问他: 那个小姐姐什么时候来报道?... 于是在众人的期待的目光…...
移动端 REM 适配
Vant 中的样式默认使用 px 作为单位,如果需要使用 rem 单位,推荐使用以下两个工具: postcss-pxtorem 是一款 postcss 插件,用于将单位转化为 rem lib-flexible 用于设置 rem 基准值 下面我们分别将这两个工具配置到项目中完成 R…...
哈希表【leetcode】
笔记:代码随想录 理论 概念 哈希表(hash table,散列表):是根据关键码的值而直接访问的数据结构,说白,数组就是一张哈希表。 哈希函数:把变量直接映射为表上的索引。 哈希碰撞&a…...
【Gem5】有关gem5模拟器的资料导航
网上有关gem5模拟器的资料、博客良莠不齐,这里记录一些总结的很好的博客与自己的学习探索。 一、gem5模拟器使用入门 官方的教程: learning_gem5:包括gem5简介、修改扩展gem5的示例、Ruby相关的缓存一致性等。gem5 Documentation࿱…...
R语言中apply系列函数详解
文章目录applylapply, sapply, vapplyrapplytapplymapplyR语言的循环效率并不高,所以并不推荐循环以及循环嵌套。为了实现循环功能的情况下,兼顾效率,R语言提供了apply系列函数,用于对规则的数据进行函数式的迭代处理。 apply a…...
AOP的另类用法 (权限校验自定义注解)
👳我亲爱的各位大佬们好😘😘😘 ♨️本篇文章记录的为 AOP的另类用法 (权限校验&&自定义注解) 相关内容,适合在学Java的小白,帮助新手快速上手,也适合复习中,面试中的大佬🙉🙉…...
【机器学习】机器学习建模调参方法总结
文章目录一、前言1.1 数据来源1.2 理论简介二、知识总结2.1 回归分析2.2 长尾分布2.3 欠拟合与过拟合2.4 正则化2.5 调参方法2.5.1 贪心调参 (坐标下降)2.5.2 网格调参GridSearchCV2.5.3 贝叶斯调参三、建模与调参3.1 线性回归3.1.1 模型建立3.1.2 查看训…...
Python数据分析师|Pandas之基础知识
版权声明:原创不易,本文禁止抄袭、转载,侵权必究! 目录一、数据分析简介二、数据分析简介三、数据查看四、知识总结五、作者Info一、数据分析简介 随着科技的发展,数据变得尤为重要,甚至有着“数据为王”&…...
macOS 13.3(22E252)/12.6.4/11.7.5正式版发布
系统介绍 3 月 28 日消息,苹果今日向 Mac 电脑用户推送了 macOS 13.3 更新(内部版本号:22E252)苹果今天还发布了macOS Monterey 12.6.4和macOS Big Sur 11.7.5,本次更新距离上次发布隔了 42 天。 macOS Ventura 带来…...
速度与兼容性功能大比拼:7款浏览器测评,哪一款更好用
还在为使用哪款浏览器而发愁吗?电脑配置低,又想浏览网页顺畅、下载速度快,那么就要挑选功能齐全、速度快的浏览器。话不多说,给大家做了7款浏览器的最全测评,看看2023年哪个浏览器更好用,更适合自己。 本次…...
【建议收藏】2023年中高级软件测试大厂面试秘籍,为你保驾护航金三银四,直通大厂
前言 从几十份顶级面试仓库和300多篇高质量面经中总结出一份全面成体系化的软件测试高级面试题集。 随着软件测试岗位技术发展的成熟,自动化、性能、框架等一下子就进入了我们的视野内,同时,软件测试自身的技术栈也正在不断扩展,…...
Cinema 4D 2023.1.3安装包下载及安装教程
[软件名称]:Cinema 4D 2023.1.3 [软件大小]: 1.0GB [安装环境]: Win11/Win 10 [软件安装包下载]: https://pan.quark.cn/s/c2324deaa028 CINEMA 4D字面意思是4D电影,不过其本身就是3D的表现软件,由德国Maxon Computer开发,以极高的运算速度和…...
IDEA vs Eclipse:使用体验对比
1. 概述 IDEA 和 Eclipse 都是常见的集成开发环境(IDE),用于编写和调试代码。它们都有一些共同的功能,例如代码编辑器、调试器、版本控制等等。但是在具体的使用体验上,它们有很多不同之处。 本文将对 IDEA 和 Eclip…...
新手学SpringCloud前需知道的5点
目录 第一点: 什么是微服务架构 第二点:为什么需要学习Spring Cloud 第三点: Spring Cloud 是什么 第四点: SpringCloud的优缺点 1、SpringCloud优点 2、SpringCloud缺点 第五点: SpringCloud由什么组成 1&…...
Java集合—HashMap为什么2倍扩容 、HashMap的key允许空值而Hashtable却不允许
目录 1. Java集合—HashMap为什么2倍扩容 1.1 从源码分析 2. 为什么HashMap的key允许空值,而Hashtable却不允许 2.1 从源码分析 1. Java集合—HashMap为什么2倍扩容 HashMap的初始容量都是2的n次幂的形式存在的,而扩容也是2倍的原来的容量进行扩容&a…...
国内、外(翻)的新闻网站推荐
也许有很多朋友和我一样,小小螺丝天天关注国家大事,总喜欢在茶余饭后关注下国内外新闻,除了新闻广播和电视之外还能有哪些方式呢?今天就给大家盘点总结一下。 一、国内 1.今日头条:链接:今日头条 推荐等…...
PHP初级教程------------------(2)
目录 运算符 赋值运算符 算术运算符 比较运算符 逻辑运算符 连接运算符 错误抑制符 三目运算符 自操作运算符 编辑 计算机码 位运算符 运算符优先级 流程控制 控制分类 顺序结构 分支结构 If分支 Switch分支 循环结构 For循环 while循环 do-while循环 循环控制 …...
js的递归函数——实现可收放的树形菜单
递归函数实现树形菜单创建假数据或者请求接口数据定义递归函数,处理数据调用函数,渲染页面效果展示完整代码树形菜单是一种常见的网站导航方式,它通常由多个层级的菜单项组成,每个菜单项可以有子菜单项。在JavaScript中࿰…...
如何高效搭建资产管理平台?众安科技告诉你答案是图技术
本⽂整理⾃ NebulaGraph x 阿⾥云计算巢专场中众安保险的⼤数据应⽤⾼级专家曾⼒带来的《众安资产在 NebulaGraph 的应⽤实践》分享,视频⻅链接。 ⼤家好,我是众安数据科学应⽤中⼼的曾⼒,今天很⾼兴在这⾥可以跟⼤家分享 NebulaGraph 在众安…...
使用mybatis-plus-generator配置一套适合你的CRUD
1、maven引入 mybatis-plus-generator 和模板引擎,你也可以使用freemarker之类的,看个人 <!-- mybatisplus代码生成器 --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactI…...
vue门户网站,滚动到可视化区域展示动画效果方案
1.准备两个工具库: (1.1) animate.css:动画库 (动画效果展示:Animate.css | A cross-browser library of CSS animations.) (1.2)wowjs: 负责滚动到可视化区域ÿ…...
【0180】PG内核读取pg_hba.conf并创建HbaLine记录(1)
文章目录 1. pg_hba.conf文件是什么?2. postmaster何时读取pg_hba.conf?2.1 pg内核使用pg_hba.conf完成客户端认证的原理2.2 读取pg_hba.conf的几个模块3. pg内核读取pg_hba.conf过程3.1 VFD机制获取文件描述符3.2 根据fd读取文件内容相关阅读: 【0178】DBeaver、pgAdmin I…...
【五】线程安全VS线程不安全
1. Java内存模型的特征 Java内存模型是围绕着在并发过程中如何处理原子性、可见性和有序性这三个特征来建立。下面逐个看下哪些操作实现这三个特性: 1.1 原子性(Atomicity) 由Java内存模型来直接保证的原子性变量操作包括 read、load、assig…...
【大屏设计方案】
大屏设计方案一、非等比放大(填充满整个屏幕)目的屏幕比例大小和设计稿的差的不多目的屏幕比例大小和设计稿的差很多二、等比放大(比如16:9)解决方案之后就可以用rem了,有两种便利的方式:也可以用media 根据不同的屏幕…...
input 标签原生实现数字选择器
在使用开源的UI框架时,实现数字选择器很容易,直接拷贝就行,如iview、elementui...等。但有时项目不使用第三方样式库,这样的话UI控件只能自己实现。笔者就遇到过这样的情况,自己实现数字选择器,下面分享下实…...
大数据项目实战之数据仓库:用户行为采集平台——第3章 用户行为日志
第3章 用户行为日志 3.1 用户行为日志概述 用户行为日志的内容,主要包括用户的各项行为信息以及行为所处的环境信息。收集这些信息的主要目的是优化产品和为各项分析统计指标提供数据支撑。收集这些信息的手段通常为埋点。 目前主流的埋点方式,有代码…...
zookeeper 学习(一):简单认识zookeeper
zookeeper 学习(一):简单认识zookeeper zk官网 zk是什么? highly reliable distributed coordination. 来自官网,高可用的分布式协调服务,应用最多的场景就是用来做其他服务中间件的协调者,我最开始接触zk ,…...
IP 归属用 Ip2region 就够了
文章目录Ip2region 简介是什么特性支持的编程语言案例实操依赖获取IP输入流转化解析IP测试抖音、微博、小红书等各平台相继上线" 网络用户IP地址显示功能", 境外显示 国家, 境内显示到 省市,且该功能无法关闭,IP地址为强…...
最小生成树kruskal-修建公路1
题目描述 L 城一共有 N 个小区。 小明是城市建设的规划者,他计划在城市修 M 条路,每修建一条路都要支付工人们相应的工钱(需要支付的工钱 = 路的长度)。 然而小明所拿到的经费并不够支付修建 M 条路的工钱,于是迫于无奈,他只能将计划改变为修建若干条路,使得 N 个小区之…...
Linux常用命令汇总
一、文件和文件夹操作 1、进入某一文件夹: cd xxx/yyy/简便记忆:改变目录,change directory,cd 2、复制文件到另一个文件: cp xxx/xxx.yyy ddd/rrr.zzz简便记忆:复制,copy,cp 第…...
vue部署包可配置后台接口地址
有时候一个部署包可能要应用于不同服务器,这就需要频繁更换后台地址。 由此引申出了部署包可直接配置后台地址的需求,这样就不需要频繁打包了。 方法 1. public 新增 config.js 文件(会被恶意修改地址,不安全) publi…...
企业电子采购系统:采购过程更规范,更透明
满足采购业务全程数字化, 实现供应商管理、采购需求、全网寻源、全网比价、电子招 投标、合同订单执行的全过程管理。 电子招标采购,是指在网上寻源和采购产品和服务的过程。对于企业和企业主来说,这是个既省钱又能提高供应链效率的有效方法…...
php 修改服务器文件上传大小限制
输入docker cp mlfnginx:/etc/nginx/conf.d/pl.conf .输入vimpl.conf 修改nginx配置文件移动到图中所示位置client_max_body_size 按键盘”i”对图中的xxM修改成需要的大小,然后按”esc”,在按”:wq”,最后按回车键输入docker cp ./pl.con…...
PICO640红外探测器配置模块verilog
目录 一、PICO640 Introduction 二、实现代码 一、PICO640 Introduction PICO640 Gen2™ is a high resolution (640x480 pixels) infrared image sensor for military, surveillance or thermography applications. It makes use of the ULIS latest, state o…...
简单易懂 关于nextTick()的理解
前言 学习Vue的过程中,大家肯定都使用过nextTick(),关于nextTick()的使用时机,大家肯定都知道,那么它的工作原理是怎样的呢,本文就简单说一下它的nextTick()的工作原理。 nextTick的使用时机 首先记住:n…...
第一节:auto.js开发环境搭建
相关学习文档:http://doc.autoxjs.com 一、下载并安装 Visual Studio Code 下载地址:https://code.visualstudio.com/ 二、安装 auto.js 插件 启动 Visual Studio Code按住 ctrlshift x输入Auto.js-Autox.js-VSCodeExt点击安装即可 三、启动 auto.…...
看他人代码小总结
针对几个功能类似的函数: 1.需要经常调试则定义一个参数比如is_debug来选择是否在调试,定义一些参数专门用于调试用,不用每次都修改这些参数,只需要修改is_debug这个参数; 2.把其中的变量(常量)单独拎出来放到一个文件…...
第四季新星计划即将开启,博客之星取消拉票你怎么看?
catalogue🌟 写在前面🌟 线下创机遇🌟 新星计划🌟 做导师可以得到什么🌟 新星计划跟原力计划有何不同?🌟 博客之星新玩法你怎么看?🌟 写在前面 哈喽,大家好&…...
AI绘画关键词网站推荐 :轻松获取百万个提示词!完全免费
一、lexica.art 该网站拥有数百万Stable Diffusion案例的文字描述和图片,可以为大家提供足够的创作灵感。 使用上也很简单,只要在搜索框输入简单的关键词或上传图片,就能为你提供大量风格不同的照片。点击照片就能看到完整的AI关键词&#…...
数据分析之Pandas(2)
3.Pandas 文章目录3.Pandas3.3 Pandas进阶3.3.1 数据重塑和轴向旋转(1)层次化索引Series的层次化索引DataFrame的层次化索引层次化——电影数据示列(2)数据旋转3.3.2 数据分组、分组运算3.3.3 离散化处理3.3.4 合并数据集…...
推荐人工智能领域十大类专业好用的深度学习预训练模型
深度学习领域出现了许多优秀的预训练模型。以下是一些常用的专业深度学习预训练模型: 图像分类模型: VGG(Visual Geometry Group)系列:VGG16、VGG19等 ResNet(Residual Network)系列:ResNet50、ResNet101等 Inception(Google Inception)系列:InceptionV3、Incepti…...
App 抓包提示网络异常怎么破?
背景 当你测试App的时候,想要通过Fiddler/Charles等工具抓包看下https请求的数据情况,发现大部分的App都提示网络异常/无数据等等信息。以“贝壳找房”为例: Fiddler中看到的请求是这样的: 你可能开始找证书的问题:是…...
Leetcode217——是否存在重复数字
217. 存在重复元素难度简单969收藏分享切换为英文接收动态反馈给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 ,返回 true ;如果数组中每个元素互不相同,返回 false 。示例 1:输入:nums [1,2,3,1]输出&…...
一文搞懂车载系统开发学习路线
前言 随着汽车技术的快速发展和智能化趋势的加强,车载信息娱乐系统已经成为现代汽车不可或缺的一部分。因此,车载软件市场正在迅速增长,这为Android应用开发提供了新的机会。恰好近年来大环境不是很理想,车载开发不失为Android应…...
HCIE学习笔记----OSPF详解
OSPF邻居建立的条件 OSPF建立邻居“41”条件总结 4个一致 一个不一致 1.保证接口的前缀 网络信息一致 2.保证ospf区域号和区域类型一致 3.hello包间隔时间和死亡时间一致 4.认证类型和认证认证信息一致 5.路由器的ID不一致 保证唯一性 一-----OSPF 邻接关系建立过程与状…...
齐护K210系列教程(二十七)_语音识别
语音识别 1.烧录固件和模型2.语音识别程序2.1训练并识别2.2使用本地文件语音识别 3.课程资源联系我们 1.烧录固件和模型 注:本应用只适用于有麦克风功能的型号:AIstart_pro、AIstart_掌机、AIstart_Mini, 其它型号不支持! 机器码生成以及模…...
tomcat--应用部署
tomcat根目录结构 Tomcat中默认网站根目录是/usr/local/apache-tomcat-8.5.100/webapps/在Tomcat的webapps目录中,有个非常特殊的目录ROOT,它就是网站默认根目录。将eshop解压后的文件放到这个/usr/local/apache-tomcat-8.5.100/webapps/ROOT中。bbs解压…...
「TypeScript系列」TypeScript 条件语句
文章目录 一、TypeScript 条件语句1. if 语句2. if...else 语句3. if...else if...else 语句4. switch 语句 二、应用场景1. 用户权限检查2. 数值判断3. 字符串匹配4. 复杂逻辑判断5. 联合类型与条件语句 三、if...else 语句的规则1. 基本结构:2. 条件表达式&#x…...
Java—如何判断两个浮点数相等
结论 一旦有浮点型数据参与运算的结果,一定不要使用 “ ” 与其比较。 提出问题 我们知道在Java中浮点数float 和 double 的值不能很精准的表示一个小数,因为会有精度损失。 下面来看一个例子: public class FloatTest {public static …...
win11设置管理员账户
今天早上,删除一个文件,删不了,就随手误点击了修改权限,把当前用户给修改成标准了,然后还直接重启电脑了,这下麻烦大了,在进入虽然使用没啥影响,但是,和系统有关的所有操…...
JAVA面试库
1、基础 1.1、面向对象编程有哪些特性 1、抽象 抽象就是对同一个目标的共有的属性、特征、方法、功能、行为等进行抽取并归纳总结,它是一种将复杂现实简单化为模型的过程,它关注的是对象行为,而不用关注具体的实现细节。 在面向对象编程中…...
Unity之Image图片挖洞
最近开发一款打地鼠小游戏,地鼠是3D的,身体比较庞大,管道比较窄小,所以管道其实没办法将地鼠完全遮盖,于是想了一下几个方法。 1,让美术把3D物体裁剪掉,让地鼠的形态体积不至于露出UIÿ…...
【C语言】指针(二)
目录 一、传值调用和传址调用 二、数组名的理解 三、通过指针访问数组 四、一维数组传参的本质 五、指针数组 六、指针数组模拟实现二维数组 一、传值调用和传址调用 指针可以用在哪里呢?我们看下面一段代码: #include <stdio.h>void Swap(i…...
【半夜学习MySQL】复合查询(含多表查询、自连接、单行/多行子查询、多列子查询、合并查询等详解)
🏠关于专栏:半夜学习MySQL专栏用于记录MySQL数据相关内容。 🎯每天努力一点点,技术变化看得见 文章目录 回顾基本查询多表查询自连接子查询单行子查询多行子查询多列子查询在from子句中使用子查询合并查询 回顾基本查询 下面使用…...
使用 cloudflare 免费服务,搭建临时邮箱,无需暴露自己的真实邮箱地址,保护个人隐私
使用 cloudflare 免费服务,搭建临时邮箱 地址 在线演示 🌐Github地址 https://github.com/find-xposed-magisk/cloudflare_temp_email 功能/TODO Cloudflare D1 作为数据库 使用 Cloudflare Pages 部署前端 使用 Cloudflare Workers 部署后端 email 转…...