概念与原理
- 什么是IOC
- 控制反转,把对象创建和对象之间的调用过程,交给Spring进行管理
- 使用IOC目的:为了降低耦合度
- 做入门案例就是IOC实现
- IOC底层原理
- XML解析,工厂模式,反射
- 画图讲解IOC底层原理
IOC(BeanFactory接口)
- IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
- Spring提供IOC容器实现的两种方式:(两个接口)
- BeanFactory: IOC容器基本实现,是Spring内部的使用接口,不提供开发人员进行使用
- *加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象
- ApplicationContext: BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员进行使用
- *加载配置文件时候就会把在配置文件对象进行创建
- ApplicationContext接口有实现类
IOC操作Bean管理(概念)
- 什么是Bean管理
- Bean管理指的是两个操作
- Spring创建对象
- Spring注入属性
- Bean管理操作有两种方式
- 基于XML配置文件实现
- 基于注解方式实现
IOC操作Bean管理(基于XML方式)
- 基于XML方式创建对象
- 在Spring配置文件中,使用Bean标签,标签里面添加对应属性,就可以实现对象创建
- ID属性: 唯一标识
- class属性: 类全路径(包类路径)
- 创建对象的时候,默认也是执行无参数构造方法完成对象创建
- 基于XML方式注入属性
- DI : 依赖注入,就是注入属性
- 第一种注入方式: 使用set方法进行注入
使用Set方法进行注入
package com.dance.spring5;public class Book {//创建属性private String bname;private String bauthor;//创建属性对应的 set 方法public void setBname(String bname) {this.bname = bname;}public void setBauthor(String bauthor) {this.bauthor = bauthor;}@Overridepublic String toString() {return \"Book{\" +\"bname=\'\" + bname + \'\\\'\' +\", bauthor=\'\" + bauthor + \'\\\'\' +\'}\';}public static void main(String[] args) {Book book = new Book();book.setBname(\"flower\");System.out.println(book);}}
在Spring配置文件配置对象创建,配置属性注入
<!--name : 属性名value : 属性值--><bean id=\"book\" class=\"com.dance.spring5.Book\"><property name=\"bname\" value=\"dance\" /></bean>
新建测试类
@Testpublic void testBook(){// 加载Spring配置文件ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext(\"spring.xml\");// 获取BeanBook book = classPathXmlApplicationContext.getBean(\"book\", Book.class);// 调用方法System.out.println(book);}
执行结果
Book{bname=\'dance\', bauthor=\'null\'}
- 第二种注入方式:使用有参构造进行注入
- 创建类,定义属性,创建属性对应有参数构造方法
使用有参构造方法进行注入
package com.dance.spring5;public class Orders {//属性private String oname;private String address;//有参数构造public Orders(String oname,String address) {this.oname = oname;this.address = address;}@Overridepublic String toString() {return \"Orders{\" +\"oname=\'\" + oname + \'\\\'\' +\", address=\'\" + address + \'\\\'\' +\'}\';}public static void main(String[] args) {Orders orders = new Orders(\"flower\", \"北京\");System.out.println(orders);}}
在Spring配置文件中进行配置
<!-- 有参构造注入属性 --><bean id=\"orders\" class=\"com.dance.spring5.Orders\"><constructor-arg name=\"oname\" value=\"flower\"/><constructor-arg name=\"address\" value=\"北京\"/></bean>
新检测试类
@Testpublic void testOrders(){// 加载Spring配置文件ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext(\"spring.xml\");// 获取BeanOrders orders = classPathXmlApplicationContext.getBean(\"orders\", Orders.class);// 调用方法System.out.println(orders);}
执行结果
Orders{oname=\'flower\', address=\'北京\'}
- P命名空间注入(了解)
- 使用P命名空间注入可以简化XML配置方式
使用P命名空间进行注入
在配置文件中加入P命名空间的校验
xmlns:p=\"http://www.springframework.org/schema/p\"
配置Spring文件
<!-- 使用P命名空间注入--><bean id=\"ordersP\" class=\"com.dance.spring5.Orders\" p:oname=\"dance\" p:address=\"河北\" />
修改Orders类
注意:因为P命名空间注入依赖于Set方法所以增加setter and getter
package com.dance.spring5;public class Orders {//属性private String oname;private String address;public String getOname() {return oname;}public void setOname(String oname) {this.oname = oname;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public Orders() {}//有参数构造public Orders(String oname,String address) {this.oname = oname;this.address = address;}@Overridepublic String toString() {return \"Orders{\" +\"oname=\'\" + oname + \'\\\'\' +\", address=\'\" + address + \'\\\'\' +\'}\';}public static void main(String[] args) {Orders orders = new Orders(\"flower\", \"北京\");System.out.println(orders);}}
新建测试类
@Testpublic void testOrdersP(){// 加载Spring配置文件ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext(\"spring.xml\");// 获取BeanOrders orders = classPathXmlApplicationContext.getBean(\"ordersP\", Orders.class);// 调用方法System.out.println(orders);}
执行结果
Orders{oname=\'dance\', address=\'河北\'}
IOC操作Bean管理(XML注入其他类型属性)
字面量
null值
<bean id=\"orderType\" class=\"com.dance.spring5.Orders\"><property name=\"address\"><null /></property></bean>
属性值包含特殊符号
属性值包含特殊符号
- 把<>进行转义 < >
- 使用CDATA
<bean id=\"orderType\" class=\"com.dance.spring5.Orders\"><property name=\"address\"><null /></property><property name=\"oname\"><!--CDATA--><value><![CDATA[ <<Spring5 API>> ]]></value></property></bean>
注入属性-外部Bean
(1)创建两个类 service 类和 dao 类
(2)在 service 调用 dao 里面的方法
(3)在 spring 配置文件中进行配置
新建UserDao
package com.dance.spring5.dao;public class UserDao {public void update(){System.out.println(\"update to database .....\");}}
新建UserService
package com.dance.spring5.service;import com.dance.spring5.dao.UserDao;public class UserService {public UserDao userDao;public void add(){System.out.println(\"add......\");userDao.update();}public void setUserDao(UserDao userDao){this.userDao = userDao;}}
配置Spring文件
<!-- 创建UserDao --><bean id=\"userDao\" class=\"com.dance.spring5.dao.UserDao\" /><!-- 创建UserService --><bean id=\"userService\" class=\"com.dance.spring5.service.UserService\"><!-- 采用ref引用已有的Bean --><property name=\"userDao\" ref=\"userDao\" /></bean>
新建测试类
@Testpublic void testUserService(){// 加载Spring配置文件ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext(\"spring.xml\");// 获取BeanUserService userService = classPathXmlApplicationContext.getBean(\"userService\", UserService.class);// 调用方法userService.add();}
执行结果
add......update to database .....
注入属性-内部Bean
(1)一对多关系:部门和员工 一个部门有多个员工,一个员工属于一个部门 部门是一,员工是多
(2)在实体类之间表示一对多关系,员工表示所属部门,使用对象类型属性进行表示
新建部门类
package com.dance.spring5;public class Dept {private String dname;public void setDname(String dname) {this.dname = dname;}@Overridepublic String toString() {return \"Dept{\" +\"dname=\'\" + dname + \'\\\'\' +\'}\';}}
新建员工类
package com.dance.spring5;public class Emp {private String ename;private String gender;private Dept dept;public void setEname(String ename) {this.ename = ename;}public void setGender(String gender) {this.gender = gender;}public void setDept(Dept dept) {this.dept = dept;}@Overridepublic String toString() {return \"Emp{\" +\"ename=\'\" + ename + \'\\\'\' +\", gender=\'\" + gender + \'\\\'\' +\", dept=\" + dept +\'}\';}}
配置Spring文件
<bean id=\"emp\" class=\"com.dance.spring5.Emp\"><property name=\"ename\" value=\"flower\" /><property name=\"gender\" value=\"男\" /><property name=\"dept\"><bean id=\"dept\" class=\"com.dance.spring5.Dept\"><property name=\"dname\" value=\"研发部\" /></bean></property></bean>
新建测试类
@Testpublic void testEmp(){// 加载Spring配置文件ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext(\"spring.xml\");// 获取BeanEmp emp = classPathXmlApplicationContext.getBean(\"emp\", Emp.class);// 调用方法System.out.println(emp);}
执行结果
Emp{ename=\'flower\', gender=\'男\', dept=Dept{dname=\'研发部\'}}
注入属性-级联赋值
第一种写法
<bean id=\"dept2\" class=\"com.dance.spring5.Dept\"><property name=\"dname\" value=\"研发部\" /></bean><bean id=\"emp2\" class=\"com.dance.spring5.Emp\"><property name=\"ename\" value=\"dance\" /><property name=\"gender\" value=\"女\" /><property name=\"dept\" ref=\"dept2\" /></bean>
第二种写法
emp类增加get方法
public Dept getDept() {return dept;}
<bean id=\"emp3\" class=\"com.dance.spring5.Emp\"><property name=\"ename\" value=\"dance\" /><property name=\"gender\" value=\"女\" /><property name=\"dept\" ref=\"dept2\" /><property name=\"dept.dname\" value=\"财务部\" /></bean>
IOC操作Bean管理(xml注入集合属性)
XML注入集合属性
- 注入数组类型属性
- 注入List集合类型属性
- 注入Map集合类型属性
新建学生类
package com.dance.spring.learn.collection;import java.util.Arrays;import java.util.List;import java.util.Map;import java.util.Set;public class Stu {//1 数组类型属性private String[] courses;//2 list 集合类型属性private List list;//3 map 集合类型属性private Map<String,String> maps;//4 set 集合类型属性private Set sets;public void setSets(Set sets) {this.sets = sets;}public void setCourses(String[] courses) {this.courses = courses;}public void setList(List 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=\"stu\" class=\"com.dance.spring.learn.collection.Stu\"><!-- 数组--><property name=\"courses\"><array><value>Java</value><value>Spring</value></array></property><!-- 集合--><property name=\"list\"><list><value>IOC</value><value>AOP</value></list></property><!-- Set--><property name=\"sets\"><set><value>Mysql</value><value>Oracle</value></set></property><!-- map--><property name=\"maps\"><map><entry key=\"name\" value=\"flower\" /><entry key=\"age\" value=\"21\" /></map></property></bean>
新建测试类
@Testpublic void test1(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext(\"Spring.xml\");Stu stu = applicationContext.getBean(\"stu\", Stu.class);System.out.println(stu);}
执行结果
Stu{courses=[Java, Spring], list=[IOC, AOP], maps={name=flower, age=21}, sets=[Mysql, Oracle]}
在集合中设置对象类型值
新建课程类
package com.dance.spring.learn.collection;/*** 课程类*/public class Course {private String cname;public String getCname() {return cname;}public void setCname(String cname) {this.cname = cname;}@Overridepublic String toString() {return \"Course{\" +\"cname=\'\" + cname + \'\\\'\' +\'}\';}}
修改学生类
package com.dance.spring.learn.collection;import java.util.Arrays;import java.util.List;import java.util.Map;import java.util.Set;public class Stu {//1 数组类型属性private String[] courses;//2 list 集合类型属性private List list;//3 map 集合类型属性private Map<String,String> maps;//4 set 集合类型属性private Set sets;// 5 list 对象集合private List courseList;public void setCourseList(List courseList) {this.courseList = courseList;}public void setSets(Set sets) {this.sets = sets;}public void setCourses(String[] courses) {this.courses = courses;}public void setList(List 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 +\'}\';}}
在Spring中进行配置
<!-- 创建多个Course--><bean id=\"cs1\" class=\"com.dance.spring.learn.collection.Course\"><property name=\"cname\" value=\"语文\" /></bean><bean id=\"cs2\" class=\"com.dance.spring.learn.collection.Course\"><property name=\"cname\" value=\"数学\" /></bean><bean id=\"stu\" class=\"com.dance.spring.learn.collection.Stu\"><!-- 数组--><property name=\"courses\"><array><value>Java</value><value>Spring</value></array></property><!-- 集合--><property name=\"list\"><list><value>IOC</value><value>AOP</value></list></property><!-- Set--><property name=\"sets\"><set><value>Mysql</value><value>Oracle</value></set></property><!-- map--><property name=\"maps\"><map><entry key=\"name\" value=\"flower\" /><entry key=\"age\" value=\"21\" /></map></property><!-- list Object--><property name=\"courseList\"><list><ref bean=\"cs1\" /><ref bean=\"cs2\" /></list></property></bean>
测试
使用之前的测试类
执行结果
Stu{courses=[Java, Spring], list=[IOC, AOP], maps={name=flower, age=21}, sets=[Mysql, Oracle], courseList=[Course{cname=\'语文\'}, Course{cname=\'数学\'}]}
提取集合注入部分
新建书类
package com.dance.spring.learn.collection;import java.util.List;public class Book {private List books;public void setBooks(List books) {this.books = books;}@Overridepublic String toString() {return \"Book{\" +\"books=\" + books +\'}\';}}
在Spring中进行配置
增加命名空间
xmlns:util=\"http://www.springframework.org/schema/util\"http://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util.xsd
配置bookList
<util:list id=\"bookList\"><value>Java</value><value>C++</value><value>Go</value></util:list><bean id=\"book\" class=\"com.dance.spring.learn.collection.Book\"><property name=\"books\" ref=\"bookList\" /></bean>
新建测试类
@Testpublic void test2(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext(\"Spring.xml\");Book book = applicationContext.getBean(\"book\", Book.class);System.out.println(book);}
执行结果
Book{books=[Java, C++, Go]}
IOC操作Bean管理(FactoryBean)
- Spring有两种类型Bean,一种普通Bean,另外一种是工厂Bean(FactoryBean)
普通Bean
在配置文件中定义Bean的类型就是返回类型
创建MyBean类
package com.dance.spring.learn.factorybean;public class MyBean {public void speak(){System.out.println(\"哈哈哈\");}}
在Spring中配置
<bean id=\"myBean\" class=\"com.dance.spring.learn.factorybean.MyBean\" />
新建测试类
@Testpublic void test3(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext(\"Spring.xml\");MyBean myBean = applicationContext.getBean(\"myBean\", MyBean.class);myBean.speak();}
执行结果
哈哈哈
工厂Bean
在配置文件定义Bean类型可以和返回类型不一致
修改MyBean
实现FactoryBean接口,泛型为Course
实现接口里面的方法,在实现的方法中定义返回的 bean 类型
package com.dance.spring.learn.factorybean;import com.dance.spring.learn.collection.Course;import org.springframework.beans.factory.FactoryBean;public class MyBean implements FactoryBean {public void speak(){System.out.println(\"哈哈哈\");}@Overridepublic Course getObject() throws Exception {Course course = new Course();course.setCname(\"JDOS实战\");return course;}@Overridepublic Class<?> getObjectType() {return null;}@Overridepublic boolean isSingleton() {return FactoryBean.super.isSingleton();}}
测试
使用普通Bean的测试
org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named \'myBean\' is expected to be of type \'com.dance.spring.learn.factorybean.MyBean\' but was actually of type \'com.dance.spring.learn.collection.Course\'at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:395)at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:207)at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1114)at com.dance.spring.learn.testdemo.TestSpring5Demo.test3(TestSpring5Demo.java:39)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:498)at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)at org.junit.runners.ParentRunner.run(ParentRunner.java:413)at org.junit.runner.JUnitCore.run(JUnitCore.java:137)at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
显示类型错误
修改测试类
@Testpublic void test3(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext(\"Spring.xml\");Course myBean = applicationContext.getBean(\"myBean\", Course.class);System.out.println(myBean);}
执行结果
Course{cname=\'JDOS实战\'}
IOC操作Bean管理(Bean的作用域)
Bean的默认作用域
新建测试类
去掉Book类的toString方法
package com.dance.spring.learn.collection;import java.util.List;public class Book {private List books;public void setBooks(List books) {this.books = books;}}
新建单元测试
@Testpublic void test4(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext(\"Spring.xml\");Book book1 = applicationContext.getBean(\"book\", Book.class);Book book2 = applicationContext.getBean(\"book\", Book.class);System.out.println(book1);System.out.println(book2);}
执行结果
com.dance.spring.learn.collection.Book@2a40cd94com.dance.spring.learn.collection.Book@2a40cd94
通过执行结果可以看出,在Spring中Bean的作用域默认是单例的
设置Bean的作用域
- 在Spring配置文件Bean标签里面有属性(Scope)用于设置单实例还是多实例
- Scope属性值
- 第一个值 默认值,singleton, 表示单实例对象
- 第二个值, prototype, 表示是多实例对象
- Singleton和Prototype的区别
- singleton 单实例, prototype 多实例
- 设置scope值为singleton时,加载Spring配置文件时就会创建单实例对象,设置scope值为prototype时,不是在加载Spring配置文件时候创建对象,在调用getBean方法时,才会创建多实例对象(就是每次New一个新的)
其他的我记得还有
request和session
request:一次请求
session:一次会话
想详细了解的话可以看一下:https://blog.csdn.net/kongmin_123/article/details/82048392
我感觉写的很好,但是一般没啥用,一般使用的话都是单例的,也就是默认的,在SpringBoot中也都是单例使用的
修改Spring配置
修改为多实例对象
<bean id=\"book\" class=\"com.dance.spring.learn.collection.Book\" scope=\"prototype\"><property name=\"books\" ref=\"bookList\" /></bean>
使用Test4测试
就是上面默认作用域的测试类
执行结果
com.dance.spring.learn.collection.Book@2a40cd94com.dance.spring.learn.collection.Book@f4168b8
通过结果可以看出,对象的内存地址不一样,所以是多实例对象
IOC操作Bean管理(Bean的生命周期)
生命周期
从对象创建到对象销毁的过程
Bean的生命周期
- 通过构造器创建Bean实例(无参数构造)
- 为Bean的属性设置值和对其他Bean的引用(调用Set方法)
- 调用Bean的初始化方法(需要进行配置初始化方法)
- Bean可以使用了(对象获取到了)
- 当容器关闭时,调用Bean的销毁方法(需要进行配置销毁的方法)
生命周期样例
新建Orders类
package com.dance.spring.learn.factorybean;public class Orders {private String oname;public Orders() {System.out.println(\"生命周期调用链: 第一步\");}public void setOname(String oname) {this.oname = oname;System.out.println(\"生命周期调用链: 第二步\");}public void init(){System.out.println(\"生命周期调用链: 第三步\");}public void destroy(){System.out.println(\"生命周期调用链: 第五步\");}}
在Spring中配置
<bean id=\"orders\" class=\"com.dance.spring.learn.factorybean.Orders\" init-method=\"init\" destroy-method=\"destroy\"><property name=\"oname\" value=\"啊哈哈哈~\" /></bean>
新建测试类
@Testpublic void test5(){ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(\"Spring.xml\");Orders orders = applicationContext.getBean(\"orders\", Orders.class);System.out.println(\"生命周期调用链: 第四步\");// 手动销毁容器applicationContext.close();}
执行结果
生命周期调用链: 第一步生命周期调用链: 第二步生命周期调用链: 第三步生命周期调用链: 第四步生命周期调用链: 第五步
Bean的后置处理器
后置处理器的生命周期位于初始化第三步的前后,整合后就是7步
- 通过构造器创建Bean实例(无参数构造)
- 为Bean的属性设置值和对其他Bean的引用(调用Set方法)
- 把Bean的实例传递给Bean的后置处理器(postProcessBeforeInitialization)
- 调用Bean的初始化方法(需要进行配置初始化方法)
- 把Bean的实例传递给Bean的后置处理器(postProcessAfterInitialization)
- Bean可以使用了(对象获取到了)
- 当容器关闭时,调用Bean的销毁方法(需要进行配置销毁的方法)
后置处理器样例
新建后置处理器Bean
package com.dance.spring.learn.factorybean;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.BeanPostProcessor;public class MyBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println(\"生命周期调用链: 第三步之前\");return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println(\"生命周期调用链: 第三步之后\");return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);}}
在Spring中进行配置
<bean id=\"myBeanPostProcessor\" class=\"com.dance.spring.learn.factorybean.MyBeanPostProcessor\" />
测试
调用Bean的生命周期样例测试
执行结果
生命周期调用链: 第一步生命周期调用链: 第二步生命周期调用链: 第三步之前生命周期调用链: 第三步生命周期调用链: 第三步之后生命周期调用链: 第四步生命周期调用链: 第五步
IOC操作Bean管理(XML自动装配)
什么是自动装配
根据指定装配规则(属性名称或者属性类型),Spring自动将匹配的属性值进行注入
演示自动装配过程
根据属性名称自动注入
新建Dept类
package com.dance.spring.learn.autowire;public class Dept {}
新建Emp类
package com.dance.spring.learn.autowire;public class Emp {private Dept dept;public void setDept(Dept dept) {this.dept = dept;}@Overridepublic String toString() {return \"Emp{\" +\"dept=\" + dept +\'}\';}}
在Spring中进行配置
<bean id=\"dept\" class=\"com.dance.spring.learn.autowire.Dept\" /><bean id=\"emp\" class=\"com.dance.spring.learn.autowire.Emp\" autowire=\"byName\"></bean>
byName:根据名称自动注入
byType:根据类型自动注入
新建测试类
@Testpublic void test6(){ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(\"Spring2.xml\");Emp emp = applicationContext.getBean(\"emp\", Emp.class);System.out.println(emp);}
执行结果
Emp{dept=com.dance.spring.learn.autowire.Dept@25bbf683}
根据类型自动注入
在Spring中进行配置
<bean id=\"dept\" class=\"com.dance.spring.learn.autowire.Dept\" /><bean id=\"emp\" class=\"com.dance.spring.learn.autowire.Emp\" autowire=\"byType\"></bean>
测试
使用test6进行测试
执行结果
Emp{dept=com.dance.spring.learn.autowire.Dept@3578436e}
IOC操作Bean管理(外部属性文件)
直接配置数据库信息
引入德鲁伊连接池的包
配置德鲁伊连接池
<bean id=\"dataSource\" class=\"com.alibaba.druid.pool.DruidDataSource\"><property name=\"driver\" value=\"com.mysql.jdbc.Driver\" /><property name=\"url\" value=\"jdbc:mysql://localhost:3306/userDb\" /><property name=\"username\" value=\"root\" /><property name=\"password\" value=\"123456\" /></bean>
引入外部属性文件配置数据库信息
创建外部属性文件
在src下创建jdbc.properties
jdbc.driverClass=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://localhost:3306/userDbjdbc.username=rootjdbc.password=123456
引入Context命名空间
xmlns:context=\"http://www.springframework.org/schema/context\"http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
在Spring中进行配置
<context:property-placeholder location=\"classpath:jdbc.properties\" /><bean id=\"dataSource\" class=\"com.alibaba.druid.pool.DruidDataSource\"><property name=\"driver\" value=\"${jdbc.driverClass}\" /><property name=\"url\" value=\"${jdbc.url}\" /><property name=\"username\" value=\"${jdbc.username}\" /><property name=\"password\" value=\"${jdbc.password}\" /></bean>
IOC操作Bean管理(基于注解开发)
什么是注解
- 注解是代码特殊标记,格式:@注解名称 (属性名称=属性值,属性名称=属性值)
- 注解作用范围, 类,方法,字段
- 使用注解的目的:简化xml配置
Spring针对Bean管理中创建对象提供的注解
- @Component
- @Service
- @Controller
- @Repository
上面四个注解的功能是一样的,都可用来创建Bean实例
基于注解的方式创建对象
引入依赖
开启注解扫描
<!--开启组件扫描多包配置可以使用逗号隔开,也可以写父包--><context:component-scan base-package=\"com.dance.spring.learn.service\" />
创建UserService类
@Servicepublic class UserService {public void add(){System.out.println(\"add ......\");}}
新建测试类
@Testpublic void test7(){ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext(\"Spring3-annotation.xml\");UserService userService = classPathXmlApplicationContext.getBean(\"userService\", UserService.class);userService.add();}
执行结果
add ......
开启组件扫描细节配置
<!--只扫描@Controlleruse-default-filters=\"false\" : 不使用默认的扫描过滤器context:include-filter: 包含过滤器type=\"annotation\": 类型为注解expression=\"org.springframework.stereotype.Controller\": 只扫描@Controller--><context:component-scan base-package=\"com.dance.spring.learn.service\" use-default-filters=\"false\"><context:include-filter type=\"annotation\" expression=\"org.springframework.stereotype.Controller\"/></context:component-scan><!--不扫描@Controllercontext:exclude-filter: 排除过滤器type=\"annotation\": 类型为注解expression=\"org.springframework.stereotype.Controller\": 不扫描@Controller--><context:component-scan base-package=\"com.dance.spring.learn.service\"><context:exclude-filter type=\"annotation\" expression=\"org.springframework.stereotype.Controller\"/></context:component-scan>
基于注解实现属性注入
@Autowired
根据类型进行自动装配
新建Userdao
package com.dance.spring.learn.dao;import org.springframework.stereotype.Repository;@Repositorypublic class UserDao {public void add(){System.out.println(\"add to db.....\");}}
修改UserService
package com.dance.spring.learn.service;import com.dance.spring.learn.dao.UserDao;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;@Servicepublic class UserService {@Autowiredpublic UserDao userDao;public void add(){System.out.println(\"add ......\");userDao.add();}}
新建Spring配置文件
因为之前的已经配置了很多的配置,所以在Src下新建Spring4.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\"xmlns:util=\"http://www.springframework.org/schema/util\"xmlns:context=\"http://www.springframework.org/schema/context\"xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd\"><!-- 扫描父包 learn --><context:component-scan base-package=\"com.dance.spring.learn\"/></beans>
新建测试类
@Testpublic void test8(){ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext(\"Spring4.xml\");UserService userService = classPathXmlApplicationContext.getBean(\"userService\", UserService.class);userService.add();}
执行结果
add ......add to db.....
@Qualifier
需要配合Autowired一期使用,默认为根据类型自动装配,添加@Qualifier后将根据Qualifier的value值进行按名称自动装配
修改UserService
package com.dance.spring.learn.service;import com.dance.spring.learn.dao.UserDao;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Service;@Servicepublic class UserService {@Autowired@Qualifier(value = \"userDao\")public UserDao userDao;public void add(){System.out.println(\"add ......\");userDao.add();}}
测试
使用test8进行测试
执行结果
add ......add to db.....
@Resource
既可以使用类型注入也可以使用名称注入,默认为名称注入,如果没有相同的名称那么就按类型注入,name和type都指定时,取都符合条件的
修改UserService
package com.dance.spring.learn.service;import com.dance.spring.learn.dao.UserDao;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Service;import javax.annotation.Resource;@Servicepublic class UserService {// @Autowired// @Qualifier(value = \"userDao\")// public UserDao userDao;@Resourcepublic UserDao userDao;public void add(){System.out.println(\"add ......\");userDao.add();}}
测试
使用test8进行测试
执行结果
add ......add to db.....
@Value
用于对普通值进行注入,也可以配合上面的外部属性文件采用${}方式获取配置文件值
修改UserService
package com.dance.spring.learn.service;import com.dance.spring.learn.dao.UserDao;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Service;import javax.annotation.Resource;@Servicepublic class UserService {// @Autowired// @Qualifier(value = \"userDao\")// public UserDao userDao;@Resourcepublic UserDao userDao;@Value(value = \"flower\")public String name;public void add(){System.out.println(\"add ......:\"+name);userDao.add();}}
测试
使用test8进行测试
测试结果
add ......:floweradd to db.....
去除XML,纯注解开发
创建配置类,取代XML
package com.dance.spring.learn.config;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;@Configuration@ComponentScan(basePackages = {\"com.dance.spring.learn\"})public class SpringConfig {}
新建测试类
@Testpublic void test9(){AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);UserService userService = annotationConfigApplicationContext.getBean(\"userService\", UserService.class);userService.add();}
执行结果
add ......:floweradd to db.....
完结撒花花
若有收获,就点个赞吧
作者:彼岸舞
时间:2021\\12\\13
内容关于:Java
本文属于作者原创,未经允许,禁止转发