缺点:
示例:
package com.wells.demo.ioc.tradition;
/**
* Description 传统方式: 通过 new 对象来调用,带来的问题:
* 1、耦合高:如果userDao有了新的实现,需要修改所有调用userDao的地方;
* 因此,为了降低耦合,所以需要工厂模式来做,而Spring恰恰用了:xml配置(注解)、工厂模式、反射来进行bean的创建
* Created by wells on 2020-07-18 08:26:41
*/
public class UserService {
public void delUser() {
System.out.println("delete user");
}
public static void main(String[] args) {
UserService userService = new UserService();
userService.delUser();
}
}
示例:
package com.wells.demo.ioc.xml;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Description 通过ApplicationContext读取xml配置文件创建对象
* Created by wells on 2020-07-18 08:26:41
*/
public class UserService {
public void addUser() {
System.out.println("add user");
}
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = applicationContext.getBean("userService", UserService.class);
userService.addUser();
}
}
<bean id="userService" class="com.wells.demo.ioc.xml.UserService"/>
DI:依赖注入,就是注入属性
package com.wells.demo.ioc.xml;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Description 通过set方法注入属性
* Created by wells on 2020-07-18 22:08:35
*/
public class Book {
private String bname;
private String bauthor;
public void setBname(String bname) {
this.bname = bname;
}
public void setBauthor(String bauthor) {
this.bauthor = bauthor;
}
@Override
public String toString() {
return "Book{" +
"bname='" + bname + '\'' +
", bauthor='" + bauthor + '\'' +
'}';
}
/**
* 通过set方法注入属性
*/
@Test
public void testWiredPropertyBySetter() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
Book book = applicationContext.getBean("book", Book.class);
System.out.println(book.toString());
}
}
<bean id="book" class="com.wells.demo.ioc.xml.Book">
<property name="bname" value="西游记"/>
<property name="bauthor" value="吴承恩"/>
bean>
package com.wells.demo.ioc.xml;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Description 使用有参构造方法注入属性
* Created by wells on 2020-07-18 22:14:14
*/
public class User {
private String name;
private Integer age;
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
/**
* 通过有参构造方法注入属性
*/
@Test
public void testWiredPropertyByConstructor() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
User user = applicationContext.getBean("user", User.class);
System.out.println(user.toString());
}
}
<bean id="user" class="com.wells.demo.ioc.xml.User">
<constructor-arg name="name" value="wells"/>
<constructor-arg name="age" value="18"/>
bean>
package com.wells.demo.ioc.xml;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Description 通过P名称空间注入属性
* Created by wells on 2020-07-18 22:31:53
*/
public class Person {
private String name;
private Integer age;
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Test
public void testWiredPropertyByPTag() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
Person person = applicationContext.getBean("person", Person.class);
System.out.println(person.toString());
}
}
<bean id="person" class="com.wells.demo.ioc.xml.Person" p:name="Tom" p:age="18"/>
<bean id="book" class="com.wells.demo.ioc.xml.Book">
<property name="bname" value="西游记"/>
<property name="bauthor" value="吴承恩"/>
<property name="addr">
<null/>
property>
bean>
例如: <、>
<bean id="book" class="com.wells.demo.ioc.xml.Book">
<property name="bname" value="西游记"/>
<property name="bauthor" value="吴承恩"/>
<property name="addr">
<null/>
property>
<property name="btime">
<value>]]>value>
property>
bean>
<bean id="empOut" class="com.wells.demo.ioc.xml.Emp">
<property name="ename" value="Jerry"/>
<property name="gender" value="男"/>
<property name="dept" ref="deptOut"/>
bean>
<bean id="deptOut" class="com.wells.demo.ioc.xml.Dept">
<property name="dname" value="技术部"/>
bean>
部门和员工关系
<bean id="empIn" class="com.wells.demo.ioc.xml.Emp">
<property name="ename" value="Lily"/>
<property name="gender" value="女"/>
<property name="dept">
<bean class="com.wells.demo.ioc.xml.Dept">
<property name="dname" value="测试部"/>
bean>
property>
bean>
<bean id="empLinkOne" class="com.wells.demo.ioc.xml.Emp">
<property name="ename" value="Tom"/>
<property name="gender" value="男"/>
<property name="dept" ref="dept"/>
bean>
<bean name="dept" class="com.wells.demo.ioc.xml.Dept">
<property name="dname" value="安全部"/>
bean>
<bean id="empLinkTwo" class="com.wells.demo.ioc.xml.Emp">
<property name="ename" value="Daivd"/>
<property name="gender" value="男"/>
<property name="dept" ref="dept"/>
<property name="dept.dname" value="业务部"/>
bean>
<bean id="student" class="com.wells.demo.ioc.xml.Student">
<property name="course">
<array>
<value>线性代数value>
<value>高等数学value>
array>
property>
<property name="books">
<list>
<value>《SpringBoot编程思想》value>
<value>《SpringCloud微服务实战》value>
list>
property>
<property name="teachers">
<map>
<entry key="大学物理" value="Tom"/>
<entry key="高等数学" value="Jerry"/>
map>
property>
<property name="courseList">
<list>
<ref bean="c1"/>
<ref bean="c2"/>
list>
property>
<property name="friends" ref="friends"/>
bean>
<bean id="c1" class="com.wells.demo.ioc.xml.Course" p:cname="大学物理"/>
<bean id="c2" class="com.wells.demo.ioc.xml.Course" p:cname="编译原理"/>
<util:list id="friends">
<value>Lilyvalue>
<value>Wellsvalue>
util:list>
Spring 有两种类型 bean,一种普通 bean,另外一种工厂 bean(FactoryBean)
package com.wells.demo.ioc.xml;
import org.junit.Test;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Description FactoryBean
* Created by wells on 2020-07-19 09:21:56
*/
public class MyBean implements FactoryBean<Course> {
public Course getObject() throws Exception {
Course course = new Course();
course.setCname("大学英语");
return course;
}
public Class<?> getObjectType() {
return null;
}
public boolean isSingleton() {
return false;
}
@Test
public void testFactoryBean(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
Course course = applicationContext.getBean("myBean", Course.class);
System.out.println(course.toString());
}
}
在 Spring 里面,默认情况下,bean 是单实例对象
如何设置单实例还是多实例?
singleton 和 prototype 区别
生命周期:从对象创建到对象销毁的过程
package com.wells.demo.ioc.xml;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Description Bean实例生命周期
* Created by wells on 2020-07-19 09:30:56
*/
public class Order {
private String oname;
public Order() {
System.out.println("第一步: 通过无参构造方法创建bean实例");
}
public void setOname(String oname) {
this.oname = oname;
System.out.println("第二步: 通过set方法注入属性");
}
/**
* Bean初始化方法
*/
public void initMethod() {
System.out.println("第三步: 调用bean初始化方法");
}
/**
* Bean销毁方法
*/
public void destroyMethod() {
System.out.println("第五步: 调用bean销毁方法");
}
@Override
public String toString() {
return "Order{" +
"oname='" + oname + '\'' +
'}';
}
@Test
public void testBeanLife() {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
Order order = applicationContext.getBean("order", Order.class);
System.out.println("第四步: 使用bean");
System.out.println(order.toString());
// 手动调用销毁bean实例
applicationContext.close();
}
}
<bean id="order" class="com.wells.demo.ioc.xml.Order" init-method="initMethod" destroy-method="destroyMethod" p:oname="裤子"/>
需要特别注意的是:processor是对所有的bean生效,因此如果创建多个bean,会被执行多次
package com.wells.demo.ioc.xml;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
* Description Bean处理器,需要特别注意的是:这个处理器是对所有的bean生效;所以会出现有几个bean,就执行几次
* Created by wells on 2020-07-19 09:58:12
*/
public class BeanProcess implements BeanPostProcessor {
/**
* 处理器前置方法
*/
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("处理器前置方法");
return bean;
}
/**
* 处理器后缀方法
*/
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("处理器后置方法");
return bean;
}
}
什么是自动装配?
需要注意的是:类中的属性名,需要与xml中的id名相同
public class Emp {
// ... 略
private Dept dept;
public void setDept(Dept dept) {
this.dept = dept;
}
// ... 略
@Test
public void testAutoWiredByNameInXML(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans-auto-wired.xml");
Emp emp = applicationContext.getBean("empByName", Emp.class);
System.out.println(emp.toString());
}
}
<bean id="empByName" class="com.wells.demo.ioc.xml.Emp" autowire="byName"/>
<bean id="dept" class="com.wells.demo.ioc.xml.Dept">
<property name="dname" value="运维部"/>
public class Emp {
// ... 略
private Dept dept;
public void setDept(Dept dept) {
this.dept = dept;
}
// ... 略
@Test
public void testAutoWiredByTypeInXML(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans-auto-wired.xml");
Emp emp = applicationContext.getBean("empByType", Emp.class);
System.out.println(emp.toString());
}
}
<bean id="empByType" class="com.wells.demo.ioc.xml.Emp" autowire="byType"/>
<bean id="dept2" class="com.wells.demo.ioc.xml.Dept">
<property name="dname" value="运维部"/>
bean>
需要注意的是:xml中不能出现多个类型一样的bean实例,否则会报错,如下图:
package com.wells.demo.ioc.xml;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Description
* Created by wells on 2020-07-19 10:19:12
*/
public class Blog {
private String bname;
public void setBname(String bname) {
this.bname = bname;
}
@Override
public String toString() {
return "Blog{" +
"bname='" + bname + '\'' +
'}';
}
@Test
public void testImportPorp() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans-import-prop.xml");
Blog blog = applicationContext.getBean("blog", Blog.class);
System.out.println(blog.toString());
}
}
blog.properties文件内容:
blog.bname=wells
<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">
<context:property-placeholder location="blog.properties"/>
<bean id="blog" class="com.wells.demo.ioc.xml.Blog">
<property name="bname" value="${blog.bname}"/>
bean>
beans>
Spring IOC XML