IOC操作 - 基于xml
导读
-
整篇包含两个部分创建对象、注入属性
-
注入属性中包括十个部分
① set方法注入属性
② 带参构造器注入属性
③ 特殊类型属性注入
④ 引入外部bean、内部bean和级联赋值
⑤ 集合属性注入及提取
⑥ FactoryBean
⑦ bean作用域
⑧ bean生命周期
⑨ 自动装配
⑩ 引入外部属性文件
一、xml内的bean标签属性
-
id属性:
唯一标识
-
class属性:
类的全路径,即包和类的路径
-
scope属性
signleton,单实例对象,默认值
prototype,多实例对象
request,一次请求有效,并将该值放在request作用域内
session,一次会话有效,并将该值放在session作用域内
二、创建对象
三、注入属性
四、注入属性方式一 - set方法注入属性
-
创建类,定义属性和对应的set方法
public class Book { private String bname; private String bauthor; public Book() { } public void setBname(String bname) { this.bname = bname; } public void setBauthor(String bauthor) { this.bauthor = bauthor; } }
-
xml配置文件 - set方法注入属性
<?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="book" class="com.atguigu.spring5.Book"> <property name="bname" value="On Java"></property> <property name="bauthor" value="布鲁斯·埃克尔"></property> </bean> </beans>
注:如果没有写set方法,property标签内会报错
-
p名称空间注入属性( set方法注入属性的另一种写法 )
① 添加p名称空间在配置文件中
xmlns:p="http://www.springframework.org/schema/p"
② 注入属性
<bean id="book" class="com.atguigu.spring5.Book" p:bname="图灵传" p:bauthor="jein">
③ 完整写法
<?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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="book" class="com.atguigu.spring5.Book" p:bname="图灵传" p:bauthor="jein"></bean> </beans
五、注入属性方式二 - 有参构造器注入属性
-
创建类,定义属性和带有参数的构造器
public class Orders { private String oname; private String address; public Orders() { } public Orders(String oname, String address) { this.oname = oname; this.address = address; } public void testOrder() { System.out.println(oname+"::"+address); } }
-
配置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="order" class="com.atguigu.spring5.Orders"> <constructor-arg name="oname" value="电脑"></constructor-arg> <constructor-arg name="address" value="China"></constructor-arg> </bean> </beans>
-
index:有参构造注入的另一种写法
<!-- 也可通过index,表示有参构造器内的第几个参数,但一般不使用 --> <bean id="order" class="com.atguigu.spring5.Orders"> <constructor-arg index="0" value="电脑"></constructor-arg> <constructor-arg index="1" value="China"></constructor-arg> </bean>
-
测试方法
public class TestSpring { @Test public void testOrder() { // 1.解析指定的xml文件 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml"); // 2.创建对象 Orders order = context.getBean("order", Orders.class); order.testOrder(); } }
六、注入其它类型的属性
-
字面量
就是指固定值,包括基本数据类型、对象等
-
字面量为null值
<property name="bname"><null/></property>
输出后bname的值就是null
-
字面量中包含特殊符号
<!-- 第一种方式:将特殊字符用转义字符代替,比如'>'代表'>' '<' 代表'<' --> <!-- 第二种方式--> <property name="bname" ><value><![CDATA[<<南京>>]]></value></property>
七、注入属性 - 引入外部bean
-
概念
在service层调用dao层内的类中的方法,就叫做引入外部bean
-
创建service层和dao层
// dao层 public interface UserDAO { public void add(); } public class UserDAOImpl implements UserDAO{ @Override public void add() { System.out.println("dao层 - add方法......"); } } // service层 public interface UserService { public void update(); } public class UserServiceImpl implements UserService{ // 创建UserDAO属性 private UserDAO userDAO; // 创建UserDAO属性的set方法 public void setUserDAO(UserDAO userDAO) { this.userDAO = userDAO; } @Override public void update() { System.out.println("service层 - update方法..........."); userDAO.add(); } }
-
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"> <!-- service的对象创建 --> <bean id="userService" class="com.atguigu.spring5.service.UserServiceImpl"> <!-- 注入UserDAO属性 name:类内的属性名称 ref:dao对象创建bean标签内的id值 --> <property name="userDAO" ref="userDAO"/> </bean> <!-- dao对象创建 --> <bean id="userDAO" class="com.atguigu.spring5.dao.UserDAOImpl"></bean> </beans>
八、注入属性 - 内部bean和级联赋值
-
用途
解决数据库表与表之间的一对一、一对多、多对多关系的属性注入
-
一对多
一个部门有多个员工
// 部门类 public class Dept { private String dname; public void setDname(String dname) { this.dname = dname; } } // 员工类 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; } }
-
内部bean
一个bean内嵌套另一个bean
<?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="emp" class="com.atguigu.spring5.bean.Emp"> <!-- 注入两个基本属性 --> <property name="ename" value="lucy"></property> <property name="gender" value="女"></property> <!-- 注入对象类型属性 --> <property name="dept"> <!-- 内部bean --> <bean id="dname" class="com.atguigu.spring5.bean.Dept"> <property name="dname" value="安保部"></property> </bean> </property> </bean> </beans>
-
级联赋值
<?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="emp" class="com.atguigu.spring5.bean.Emp"> <!-- 注入两个基本属性 --> <property name="ename" value="lucy"></property> <property name="gender" value="女"></property> <!-- 级联赋值:ref为引用类型属性所在类的对象创建bean中的id值 --> <property name="dept" ref="dept"></property> </bean> <bean id="dept" class="com.atguigu.spring5.bean.Dept"> <property name="dname" value="安保部"></property> </bean> </beans>
-
级联赋值的另一种写法
这种写法,要做Emp类中创建get方法
<bean id="emp" class="com.atguigu.spring5.bean.Emp"> <!-- 注入两个基本属性 --> <property name="ename" value="lucy"></property> <property name="gender" value="女"></property> <!-- 级联赋值 --> <property name="dept" ref="dept"></property> <property name="dept.dname" value="财务部"></property> </bean> <bean id="dept" class="com.atguigu.spring5.bean.Dept"> <property name="dname" value="安保部"></property> </bean>
九、注入属性 - 集合
-
创建类
public class Stu { // 1.数组类型的属性 private String[] courses; // 2.List类型的属性 private List<String> list; // 3.Map类型的属性 private Map<String,String> map; // 4.Set类型的属性 private Set<String> sets; // 5.List类型,值是对象类型的属性 private List<Course> courseList; public void setCourses(String[] courses) { this.courses = courses; } public void setList(List<String> list) { this.list = list; } public void setMap(Map<String, String> map) { this.map = map; } public void setSets(Set<String> sets) { this.sets = sets; } public void setCourseList(List<Course> courseList) { this.courseList = courseList; } }
-
在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"> <bean id="stu" class="com.atguigu.spring5.conllections.Stu"> <!-- 1.数组类型的属性注入 --> <property name="courses"> <array> <value>Java</value> <value>Spring</value> </array> </property> <!-- 2.List类型的属性注入 --> <property name="list"> <list> <value>张三</value> <value>小三</value> </list> </property> <!-- 3.Map类型的属性注入 --> <property name="map"> <map> <entry key="JAVA" value="java"></entry> <entry key="LINUX" value="linux"></entry> </map> </property> <!-- 4.Set类型的属性注入 --> <property name="sets"> <set> <value>SpringMVC</value> <value>MyBatis</value> </set> </property> </bean> </beans>
-
在集合中设置对象类型的属性
<bean id="stu" class="com.atguigu.spring5.conllections.Stu"> <!-- 5.List类型,值是对象类型的属性注入 --> <property name="courseList"> <list> <ref bean="course1"></ref> <ref bean="course2"></ref> </list> </property> </bean> <!-- 创建多个Course对象 --> <bean id="course1" class="com.atguigu.spring5.conllections.Course"> <property name="cname" value="Spring5框架"></property> </bean> <bean id="course2" class="com.atguigu.spring5.conllections.Course"> <property name="cname" value="MyBatis框架"></property> </bean>
十、注入属性 - 集合注入的共用部分提取及注入
-
在Spring配置文件中引入名称空间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/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> </beans>
-
提取List集合类型的属性
<util:list id="bookList"> <value>On Java</value> <value>Think In Java</value> <value>Linux and Shell</value> </util:list> <bean id="stu" class="com.atguigu.spring5.conllections.Stu"> <!-- 提取List集合类型属性的注入 --> <property name="list" ref="bookList"></property> </bean>
-
提取List集合类型属性的注入
<bean id="stu" class="com.atguigu.spring5.conllections.Stu"> <property name="list" ref="bookList"></property> </bean>
十一、FactoryBbean类型
-
普通bean
在配置文件中,bean中的class是哪个对象类型,返回的也是该对象类型
-
工厂bean(FactoryBean)
在配置文件中,定义bean中的类型和返回值类型可以不一样
-
工厂bean的使用
创建类,让这个类作为工厂bean,实现接口FactoryBean
public class MyBean implements FactoryBean<Course> { // 定义返回bean @Override public Course getObject() throws Exception { Course course = new Course(); course.setCname("On Java"); return course; } // 返回类型 @Override public Class<?> getObjectType() { return null; } // 是否为单例 @Override public boolean isSingleton() { return FactoryBean.super.isSingleton(); } }
在Spring配置文件内配置工厂bean
<bean id="myBean" class="com.atguigu.spring5.factorybean.MyBean"></bean>
测试返回
public class TestSpring5 { @Test public void testStu() { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml"); Course course = context.getBean("myBean", Course.class); System.out.println("myBean = " + course); } } /* 注: 如果写成: MyBean myBean = context.getBean("myBean", MyBean.class); 会报错: Bean named 'myBean' is expected to be of type 'com.atguigu.spring5.factorybean.MyBean' but was actually of type 'com.atguigu.spring5.conllections.Course' 报错翻译: 名为“myBean”的 Bean 应为“com.atguigu.spring5.factorybean.MyBean”类型, 但实际上是“com.atguigu.spring5.conllections.Course”类型 */
十二、bean作用域
-
作用域:scope属性
就是设置bean创建对象是单实例还是多实例
signleton,单实例对象,默认值
prototype,多实例对象
request,一次请求有效,并将该值放在request作用域内
session,一次会话有效,并将该值放在session作用域内
-
单实例
-
多实例
-
signleton与prototype的区别
signleton:加载Spring配置文件时,就创建了该对象
prototype:调用getBean方法时,才创建对象
十三、bean生命周期
-
生命周期
对象从创建到销毁的过程
-
bean生命周期
① 通过构造器创建bean实例(无参构造器)
② 为bean的属性设置值和对其他bean引用
③ 把bean实例传递到bean后置处理器的方法 postProcessBeforeInitialization
④ 调用bean的初始化的方法(需要进行配置)
⑤ 把bean实例传递到bean后置处理器的方法 postProcessAfterInitialization
⑥ bean可以使用了
⑦ 当容器关闭的时候,调用bean的销毁方法(需要进行配置)
-
新建一个类
public class Course { private String cname; public Course() { System.out.println("Bean生命周期第一步:执行无参构造器,创建bean实例"); } public void setCname(String cname) { this.cname = cname; System.out.println("Bean生命周期第二步:调用set方法,注入属性值"); } public void initMethod() { System.out.println("Bean生命周期第三步:执行初始化方法"); } public void destroyMethod() { System.out.println("Bean生命周期第五步:执行销毁方法"); } }
-
创建一个后置处理类
会为所有的bean添加该处理器
// 实现了BeanPostProcessor接口,故成为了一个后置处理类 public class MyBeanPost implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("Bean生命周期第三步:在初始化之前执行"); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("Bean生命周期第五步:在初始化之后执行"); 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" 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 http://www.springframework.org/schema/util/spring-util.xsd"> <bean id="course" class="com.atguigu.spring5.conllections.Course" init-method="initMethod" destroy-method="destroyMethod"> <property name="cname" value="On Java"></property> </bean> <!-- 配置后置处理器,该处理器会为所有的bean都添加上后置处理方法 --> <bean id="myBeanPost" class="com.atguigu.spring5.conllections.MyBeanPost"></bean> </beans>
-
测试方法
public class TestSpring5 { @Test public void testCourse() { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml"); Course course = context.getBean("course", Course.class); System.out.println("Bean生命周期第四步 获取创建的bean对象" + course); // 手动让bean销毁 context.close(); } }
-
执行后的结果
十四、xml自动装配
-
概念
根据指定装配规则(属性名称或属性类型),Spring自动将匹配的属性值进行注入
-
自动装配属性 autowire
byName:根据属性名称注入,但是注入值bean得id值和类属性名称要一样才能够自动匹配
byType:根据属性类型注入,但是匹配类型的bean只能够创建一个对象,否则会报错
-
新建两个演示类
public class Dept { private String dname; public void setDname(String dname) { this.dname = dname; } @Override public String toString() { return "Dept{" + "dname='" + dname + '\'' + '}'; } } public class Emp { private Dept dept; public void setDept(Dept dept) { this.dept = dept; } @Override public String toString() { return "Emp{" + "Dept='" + dept + '\'' + '}'; } public void add() { System.out.println(dept); } }
-
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 http://www.springframework.org/schema/util/spring-util.xsd"> <!-- 根据属性名称进行自动匹配 --> <!-- <bean id="emp" class="com.atguigu.spring5.autowire.Emp" autowire="byName"></bean>--> <!-- 根据属性l进行自动匹配 --> <bean id="emp" class="com.atguigu.spring5.autowire.Emp" autowire="byType"></bean> <bean id="dept" class="com.atguigu.spring5.autowire.Dept"></bean> </beans>
十五、引入外部属性文件
-
导入MySQL数据库和数据库连接池druid的jar包
-
固定格式配置
<?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"> <!-- druid连接池固定配置 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"> <property name="url" value="jdbc:mysql://localhost:8080/bookshop" /> <property name="username" value="root" /> <property name="password" value="123456" /> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver" /> </bean> </beans>
-
引入外部属性文件配置
创建 jdbc.properties 配置文件
prop.driverClassName=com.mysql.cj.jdbc.Driver prop.url=jdbc:mysql://localhost:3306/qqzonedb2?rewriteBatchedStatements=true&serverTimezone=UTC&useUnicode=true\ &characterEncoding=utf-8&useSSL=false prop.username=root prop.password=7989775nx initialSize=5 maxActive=10 maxWait=3000
spring配置文件
<?xml version="1.0" encoding="UTF-8"?> <-- 1.创建context空间名称 --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 2.引入外部属性文件 --> <context:property-placeholder location="classpath:jdbc.properties"/> <!-- 3.引用外部属性文件中的标签名 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"> <property name="url" value="${prop.url}" /> <property name="username" value="${prop.username}" /> <property name="password" value="${prop.password}" /> <property name="driverClassName" value="${prop.driverClassName}" /> </bean> </beans>