前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >02-Spring5 IOC容器

02-Spring5 IOC容器

作者头像
彼岸舞
发布2021-12-14 19:56:31
4500
发布2021-12-14 19:56:31
举报

概念与原理

  1. 什么是IOC
    1. 控制反转,把对象创建和对象之间的调用过程,交给Spring进行管理
    2. 使用IOC目的:为了降低耦合度
    3. 做入门案例就是IOC实现
  2. IOC底层原理
    1. XML解析,工厂模式,反射
  3. 画图讲解IOC底层原理

IOC(BeanFactory接口)

  1. IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
  2. Spring提供IOC容器实现的两种方式:(两个接口)
    1. BeanFactory: IOC容器基本实现,是Spring内部的使用接口,不提供开发人员进行使用
    2. *加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象
    3. ApplicationContext: BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员进行使用
    4. *加载配置文件时候就会把在配置文件对象进行创建
  3. ApplicationContext接口有实现类

IOC操作Bean管理(概念)

  1. 什么是Bean管理
    1. Bean管理指的是两个操作
    2. Spring创建对象
    3. Spring注入属性
  2. Bean管理操作有两种方式
    1. 基于XML配置文件实现
    2. 基于注解方式实现

IOC操作Bean管理(基于XML方式)

  1. 基于XML方式创建对象
  1. 在Spring配置文件中,使用Bean标签,标签里面添加对应属性,就可以实现对象创建
  2. ID属性: 唯一标识
  3. class属性: 类全路径(包类路径)
  4. 创建对象的时候,默认也是执行无参数构造方法完成对象创建
  1. 基于XML方式注入属性
    1. DI : 依赖注入,就是注入属性
  2. 第一种注入方式: 使用set方法进行注入

使用Set方法进行注入

代码语言:javascript
复制
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;
    }

    @Override
    public 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配置文件配置对象创建,配置属性注入

代码语言:javascript
复制
<!--
    name : 属性名
    value : 属性值
    -->
<bean id="book" class="com.dance.spring5.Book">
  <property name="bname" value="dance" />
</bean>

新建测试类

代码语言:javascript
复制
@Test
public void testBook(){

    // 加载Spring配置文件
    ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("spring.xml");

    // 获取Bean
    Book book = classPathXmlApplicationContext.getBean("book", Book.class);

    // 调用方法
    System.out.println(book);
}

执行结果

代码语言:javascript
复制
Book{bname='dance', bauthor='null'}
  1. 第二种注入方式:使用有参构造进行注入
    1. 创建类,定义属性,创建属性对应有参数构造方法

使用有参构造方法进行注入

代码语言:javascript
复制
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;
    }

    @Override
    public String toString() {
        return "Orders{" +
                "oname='" + oname + '\'' +
                ", address='" + address + '\'' +
                '}';
    }

    public static void main(String[] args) {
        Orders orders = new Orders("flower", "北京");
        System.out.println(orders);
    }
}

在Spring配置文件中进行配置

代码语言:javascript
复制
<!-- 有参构造注入属性 -->
<bean id="orders" class="com.dance.spring5.Orders">
  <constructor-arg name="oname" value="flower"/>
  <constructor-arg name="address" value="北京"/>
</bean>

新检测试类

代码语言:javascript
复制
@Test
public void testOrders(){

    // 加载Spring配置文件
    ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("spring.xml");

    // 获取Bean
    Orders orders = classPathXmlApplicationContext.getBean("orders", Orders.class);

    // 调用方法
    System.out.println(orders);
}

执行结果

代码语言:javascript
复制
Orders{oname='flower', address='北京'}
  1. P命名空间注入(了解)
    1. 使用P命名空间注入可以简化XML配置方式

使用P命名空间进行注入

在配置文件中加入P命名空间的校验

代码语言:javascript
复制
xmlns:p="http://www.springframework.org/schema/p"

配置Spring文件

代码语言:javascript
复制
<!--    使用P命名空间注入-->
<bean id="ordersP" class="com.dance.spring5.Orders" p:oname="dance" p:address="河北" />

修改Orders类

注意:因为P命名空间注入依赖于Set方法所以增加setter and getter

代码语言:javascript
复制
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;
    }

    @Override
    public String toString() {
        return "Orders{" +
                "oname='" + oname + '\'' +
                ", address='" + address + '\'' +
                '}';
    }

    public static void main(String[] args) {
        Orders orders = new Orders("flower", "北京");
        System.out.println(orders);
    }
}

新建测试类

代码语言:javascript
复制
@Test
public void testOrdersP(){

    // 加载Spring配置文件
    ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("spring.xml");

    // 获取Bean
    Orders orders = classPathXmlApplicationContext.getBean("ordersP", Orders.class);

    // 调用方法
    System.out.println(orders);
}

执行结果

代码语言:javascript
复制
Orders{oname='dance', address='河北'}

IOC操作Bean管理(XML注入其他类型属性)

字面量

null值

代码语言:javascript
复制
<bean id="orderType" class="com.dance.spring5.Orders">
  <property name="address">
    <null />
  </property>
</bean>

属性值包含特殊符号

属性值包含特殊符号

  1. 把<>进行转义 < >
  2. 使用CDATA
代码语言:javascript
复制
<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

代码语言:javascript
复制
package com.dance.spring5.dao;

public class UserDao {
    
    public void update(){
        System.out.println("update to database .....");
    }
    
}

新建UserService

代码语言:javascript
复制
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文件

代码语言:javascript
复制
<!-- 创建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>

新建测试类

代码语言:javascript
复制
@Test
public void testUserService(){

    // 加载Spring配置文件
    ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("spring.xml");

    // 获取Bean
    UserService userService = classPathXmlApplicationContext.getBean("userService", UserService.class);

    // 调用方法
    userService.add();
}

执行结果

代码语言:javascript
复制
add......
update to database .....

注入属性-内部Bean

(1)一对多关系:部门和员工 一个部门有多个员工,一个员工属于一个部门 部门是一,员工是多

(2)在实体类之间表示一对多关系,员工表示所属部门,使用对象类型属性进行表示

新建部门类

代码语言:javascript
复制
package com.dance.spring5;

public class Dept {

    private String dname;

    public void setDname(String dname) {
        this.dname = dname;
    }

    @Override
    public String toString() {
        return "Dept{" +
                "dname='" + dname + '\'' +
                '}';
    }
}

新建员工类

代码语言:javascript
复制
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;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "ename='" + ename + '\'' +
                ", gender='" + gender + '\'' +
                ", dept=" + dept +
                '}';
    }
}

配置Spring文件

代码语言:javascript
复制
<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>

新建测试类

代码语言:javascript
复制
@Test
public void testEmp(){

    // 加载Spring配置文件
    ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("spring.xml");

    // 获取Bean
    Emp emp = classPathXmlApplicationContext.getBean("emp", Emp.class);

    // 调用方法
    System.out.println(emp);
}

执行结果

代码语言:javascript
复制
Emp{ename='flower', gender='男', dept=Dept{dname='研发部'}}

注入属性-级联赋值

第一种写法

代码语言:javascript
复制
<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方法

代码语言:javascript
复制
public Dept getDept() {
    return dept;
}
代码语言:javascript
复制
<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集合类型属性

新建学生类

代码语言:javascript
复制
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;
    }

    @Override
    public String toString() {
        return "Stu{" +
                "courses=" + Arrays.toString(courses) +
                ", list=" + list +
                ", maps=" + maps +
                ", sets=" + sets +
                '}';
    }
}

在Spring中进行配置

代码语言:javascript
复制
<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>

新建测试类

代码语言:javascript
复制
@Test
public void test1(){

    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("Spring.xml");

    Stu stu = applicationContext.getBean("stu", Stu.class);

    System.out.println(stu);

}

执行结果

代码语言:javascript
复制
Stu{courses=[Java, Spring], list=[IOC, AOP], maps={name=flower, age=21}, sets=[Mysql, Oracle]}

在集合中设置对象类型值

新建课程类

代码语言:javascript
复制
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;
    }

    @Override
    public String toString() {
        return "Course{" +
                "cname='" + cname + '\'' +
                '}';
    }
}

修改学生类

代码语言:javascript
复制
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;
    }

    @Override
    public String toString() {
        return "Stu{" +
                "courses=" + Arrays.toString(courses) +
                ", list=" + list +
                ", maps=" + maps +
                ", sets=" + sets +
                ", courseList=" + courseList +
                '}';
    }
}

在Spring中进行配置

代码语言:javascript
复制
<!--    创建多个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>

测试

使用之前的测试类

执行结果

代码语言:javascript
复制
Stu{courses=[Java, Spring], list=[IOC, AOP], maps={name=flower, age=21}, sets=[Mysql, Oracle], courseList=[Course{cname='语文'}, Course{cname='数学'}]}

提取集合注入部分

新建书类

代码语言:javascript
复制
package com.dance.spring.learn.collection;

import java.util.List;

public class Book {
    
    private List books;

    public void setBooks(List books) {
        this.books = books;
    }

    @Override
    public String toString() {
        return "Book{" +
                "books=" + books +
                '}';
    }
}

在Spring中进行配置

增加命名空间

代码语言:javascript
复制
xmlns:util="http://www.springframework.org/schema/util"
http://www.springframework.org/schema/util
       http://www.springframework.org/schema/util/spring-util.xsd

配置bookList

代码语言:javascript
复制
<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>

新建测试类

代码语言:javascript
复制
@Test
public void test2(){

    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("Spring.xml");

    Book book = applicationContext.getBean("book", Book.class);

    System.out.println(book);

}

执行结果

代码语言:javascript
复制
Book{books=[Java, C++, Go]}

IOC操作Bean管理(FactoryBean)

  1. Spring有两种类型Bean,一种普通Bean,另外一种是工厂Bean(FactoryBean)

普通Bean

在配置文件中定义Bean的类型就是返回类型

创建MyBean类

代码语言:javascript
复制
package com.dance.spring.learn.factorybean;

public class MyBean {

    public void speak(){
        System.out.println("哈哈哈");
    }

}

在Spring中配置

代码语言:javascript
复制
<bean id="myBean" class="com.dance.spring.learn.factorybean.MyBean" />

新建测试类

代码语言:javascript
复制
@Test
public void test3(){

    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("Spring.xml");

    MyBean myBean = applicationContext.getBean("myBean", MyBean.class);

    myBean.speak();

}

执行结果

代码语言:javascript
复制
哈哈哈

工厂Bean

在配置文件定义Bean类型可以和返回类型不一致

修改MyBean

实现FactoryBean接口,泛型为Course

实现接口里面的方法,在实现的方法中定义返回的 bean 类型

代码语言:javascript
复制
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("哈哈哈");
    }

    @Override
    public Course getObject() throws Exception {
        Course course = new Course();
        course.setCname("JDOS实战");
        return course;
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }

    @Override
    public boolean isSingleton() {
        return FactoryBean.super.isSingleton();
    }
}

测试

使用普通Bean的测试

代码语言:javascript
复制
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)

显示类型错误

修改测试类

代码语言:javascript
复制
@Test
public void test3(){

    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("Spring.xml");

    Course myBean = applicationContext.getBean("myBean", Course.class);

    System.out.println(myBean);

}

执行结果

代码语言:javascript
复制
Course{cname='JDOS实战'}

IOC操作Bean管理(Bean的作用域)

Bean的默认作用域

新建测试类

去掉Book类的toString方法

代码语言:javascript
复制
package com.dance.spring.learn.collection;

import java.util.List;

public class Book {

    private List books;

    public void setBooks(List books) {
        this.books = books;
    }

}

新建单元测试

代码语言:javascript
复制
@Test
public 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);

}

执行结果

代码语言:javascript
复制
com.dance.spring.learn.collection.Book@2a40cd94
com.dance.spring.learn.collection.Book@2a40cd94

通过执行结果可以看出,在Spring中Bean的作用域默认是单例的

设置Bean的作用域

  1. 在Spring配置文件Bean标签里面有属性(Scope)用于设置单实例还是多实例
  2. Scope属性值
    1. 第一个值 默认值,singleton, 表示单实例对象
    2. 第二个值, prototype, 表示是多实例对象
  3. Singleton和Prototype的区别
    1. singleton 单实例, prototype 多实例
    2. 设置scope值为singleton时,加载Spring配置文件时就会创建单实例对象,设置scope值为prototype时,不是在加载Spring配置文件时候创建对象,在调用getBean方法时,才会创建多实例对象(就是每次New一个新的)

其他的我记得还有

request和session

request:一次请求

session:一次会话

想详细了解的话可以看一下:https://blog.csdn.net/kongmin_123/article/details/82048392

我感觉写的很好,但是一般没啥用,一般使用的话都是单例的,也就是默认的,在SpringBoot中也都是单例使用的

修改Spring配置

修改为多实例对象

代码语言:javascript
复制
<bean id="book" class="com.dance.spring.learn.collection.Book" scope="prototype">
  <property name="books" ref="bookList" />
</bean>

使用Test4测试

就是上面默认作用域的测试类

执行结果

代码语言:javascript
复制
com.dance.spring.learn.collection.Book@2a40cd94
com.dance.spring.learn.collection.Book@f4168b8

通过结果可以看出,对象的内存地址不一样,所以是多实例对象

IOC操作Bean管理(Bean的生命周期)

生命周期

从对象创建到对象销毁的过程

Bean的生命周期

  1. 通过构造器创建Bean实例(无参数构造)
  2. 为Bean的属性设置值和对其他Bean的引用(调用Set方法)
  3. 调用Bean的初始化方法(需要进行配置初始化方法)
  4. Bean可以使用了(对象获取到了)
  5. 当容器关闭时,调用Bean的销毁方法(需要进行配置销毁的方法)

生命周期样例

新建Orders类

代码语言:javascript
复制
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中配置

代码语言:javascript
复制
<bean id="orders" class="com.dance.spring.learn.factorybean.Orders" init-method="init" destroy-method="destroy">
  <property name="oname" value="啊哈哈哈~" />
</bean>

新建测试类

代码语言:javascript
复制
@Test
public void test5(){

    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("Spring.xml");

    Orders orders = applicationContext.getBean("orders", Orders.class);
    System.out.println("生命周期调用链: 第四步");

    // 手动销毁容器
    applicationContext.close();

}

执行结果

代码语言:javascript
复制
生命周期调用链: 第一步
生命周期调用链: 第二步
生命周期调用链: 第三步
生命周期调用链: 第四步
生命周期调用链: 第五步

Bean的后置处理器

后置处理器的生命周期位于初始化第三步的前后,整合后就是7步

  1. 通过构造器创建Bean实例(无参数构造)
  2. 为Bean的属性设置值和对其他Bean的引用(调用Set方法)
  3. 把Bean的实例传递给Bean的后置处理器(postProcessBeforeInitialization)
  4. 调用Bean的初始化方法(需要进行配置初始化方法)
  5. 把Bean的实例传递给Bean的后置处理器(postProcessAfterInitialization)
  6. Bean可以使用了(对象获取到了)
  7. 当容器关闭时,调用Bean的销毁方法(需要进行配置销毁的方法)

后置处理器样例

新建后置处理器Bean

代码语言:javascript
复制
package com.dance.spring.learn.factorybean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("生命周期调用链: 第三步之前");
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("生命周期调用链: 第三步之后");
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}

在Spring中进行配置

代码语言:javascript
复制
<bean id="myBeanPostProcessor" class="com.dance.spring.learn.factorybean.MyBeanPostProcessor" />

测试

调用Bean的生命周期样例测试

执行结果

代码语言:javascript
复制
生命周期调用链: 第一步
生命周期调用链: 第二步
生命周期调用链: 第三步之前
生命周期调用链: 第三步
生命周期调用链: 第三步之后
生命周期调用链: 第四步
生命周期调用链: 第五步

IOC操作Bean管理(XML自动装配)

什么是自动装配

根据指定装配规则(属性名称或者属性类型),Spring自动将匹配的属性值进行注入

演示自动装配过程

根据属性名称自动注入

新建Dept类
代码语言:javascript
复制
package com.dance.spring.learn.autowire;

public class Dept {
    
}
新建Emp类
代码语言:javascript
复制
package com.dance.spring.learn.autowire;

public class Emp {

    private Dept dept;

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "dept=" + dept +
                '}';
    }
}
在Spring中进行配置
代码语言:javascript
复制
<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:根据类型自动注入

新建测试类
代码语言:javascript
复制
@Test
public void test6(){

    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("Spring2.xml");

    Emp emp = applicationContext.getBean("emp", Emp.class);

    System.out.println(emp);

}
执行结果
代码语言:javascript
复制
Emp{dept=com.dance.spring.learn.autowire.Dept@25bbf683}

根据类型自动注入

在Spring中进行配置
代码语言:javascript
复制
<bean id="dept" class="com.dance.spring.learn.autowire.Dept" />

<bean id="emp" class="com.dance.spring.learn.autowire.Emp" autowire="byType">
</bean>
测试

使用test6进行测试

执行结果
代码语言:javascript
复制
Emp{dept=com.dance.spring.learn.autowire.Dept@3578436e}

IOC操作Bean管理(外部属性文件)

直接配置数据库信息

引入德鲁伊连接池的包

配置德鲁伊连接池

代码语言:javascript
复制
<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

代码语言:javascript
复制
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/userDb
jdbc.username=root
jdbc.password=123456

引入Context命名空间

代码语言:javascript
复制
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd

在Spring中进行配置

代码语言:javascript
复制
<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管理(基于注解开发)

什么是注解

  1. 注解是代码特殊标记,格式:@注解名称 (属性名称=属性值,属性名称=属性值)
  2. 注解作用范围, 类,方法,字段
  3. 使用注解的目的:简化xml配置

Spring针对Bean管理中创建对象提供的注解

  1. @Component
  2. @Service
  3. @Controller
  4. @Repository

上面四个注解的功能是一样的,都可用来创建Bean实例

基于注解的方式创建对象

引入依赖

开启注解扫描

代码语言:javascript
复制
<!-- 
        开启组件扫描
            多包配置可以使用逗号隔开,也可以写父包    
     -->
<context:component-scan base-package="com.dance.spring.learn.service" />

创建UserService类

代码语言:javascript
复制
@Service
public class UserService {

    public void add(){
        System.out.println("add ......");
    }

}

新建测试类

代码语言:javascript
复制
@Test
public void test7(){
    ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("Spring3-annotation.xml");
    UserService userService = classPathXmlApplicationContext.getBean("userService", UserService.class);
    userService.add();
}

执行结果

代码语言:javascript
复制
add ......

开启组件扫描细节配置

代码语言:javascript
复制
<!--  
        只扫描@Controller
        use-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>

<!--  
        不扫描@Controller
        context: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
代码语言:javascript
复制
package com.dance.spring.learn.dao;

import org.springframework.stereotype.Repository;

@Repository
public class UserDao {

    public void add(){
        System.out.println("add to db.....");
    }

}
修改UserService
代码语言:javascript
复制
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;

@Service
public class UserService {

    @Autowired
    public UserDao userDao;
    
    public void add(){
        System.out.println("add ......");
        userDao.add();
    }

}
新建Spring配置文件

因为之前的已经配置了很多的配置,所以在Src下新建Spring4.xml

代码语言:javascript
复制
<?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.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
        http://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>
新建测试类
代码语言:javascript
复制
@Test
public void test8(){
    ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("Spring4.xml");
    UserService userService = classPathXmlApplicationContext.getBean("userService", UserService.class);
    userService.add();
}
执行结果
代码语言:javascript
复制
add ......
add to db.....

@Qualifier

需要配合Autowired一期使用,默认为根据类型自动装配,添加@Qualifier后将根据Qualifier的value值进行按名称自动装配

修改UserService
代码语言:javascript
复制
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;

@Service
public class UserService {

    @Autowired
    @Qualifier(value = "userDao")
    public UserDao userDao;

    public void add(){
        System.out.println("add ......");
        userDao.add();
    }

}
测试

使用test8进行测试

执行结果
代码语言:javascript
复制
add ......
add to db.....

@Resource

既可以使用类型注入也可以使用名称注入,默认为名称注入,如果没有相同的名称那么就按类型注入,name和type都指定时,取都符合条件的

修改UserService
代码语言:javascript
复制
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;

@Service
public class UserService {

//    @Autowired
//    @Qualifier(value = "userDao")
//    public UserDao userDao;
    
    @Resource
    public UserDao userDao;

    public void add(){
        System.out.println("add ......");
        userDao.add();
    }

}
测试

使用test8进行测试

执行结果
代码语言:javascript
复制
add ......
add to db.....

@Value

用于对普通值进行注入,也可以配合上面的外部属性文件采用${}方式获取配置文件值

修改UserService
代码语言:javascript
复制
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;

@Service
public class UserService {

//    @Autowired
//    @Qualifier(value = "userDao")
//    public UserDao userDao;

    @Resource
    public UserDao userDao;
    
    @Value(value = "flower")
    public String name;

    public void add(){
        System.out.println("add ......:"+name);
        userDao.add();
    }

}
测试

使用test8进行测试

测试结果
代码语言:javascript
复制
add ......:flower
add to db.....

去除XML,纯注解开发

创建配置类,取代XML

代码语言:javascript
复制
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 {

}

新建测试类

代码语言:javascript
复制
@Test
public void test9(){
    AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
    UserService userService = annotationConfigApplicationContext.getBean("userService", UserService.class);
    userService.add();
}

执行结果

代码语言:javascript
复制
add ......:flower
add to db.....
本文参与?腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-12-13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客?前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概念与原理
  • IOC(BeanFactory接口)
  • IOC操作Bean管理(概念)
  • IOC操作Bean管理(基于XML方式)
    • 使用Set方法进行注入
      • 使用有参构造方法进行注入
        • 使用P命名空间进行注入
        • IOC操作Bean管理(XML注入其他类型属性)
          • 字面量
            • null值
            • 属性值包含特殊符号
          • 注入属性-外部Bean
            • 新建UserDao
            • 新建UserService
            • 配置Spring文件
            • 新建测试类
            • 执行结果
          • 注入属性-内部Bean
            • 新建部门类
            • 新建员工类
            • 配置Spring文件
            • 新建测试类
            • 执行结果
          • 注入属性-级联赋值
            • 第一种写法
            • 第二种写法
        • IOC操作Bean管理(xml注入集合属性)
          • XML注入集合属性
            • 新建学生类
            • 在Spring中进行配置
            • 新建测试类
            • 执行结果
          • 在集合中设置对象类型值
            • 新建课程类
            • 修改学生类
            • 在Spring中进行配置
            • 测试
            • 执行结果
          • 提取集合注入部分
            • 新建书类
            • 在Spring中进行配置
            • 新建测试类
            • 执行结果
        • IOC操作Bean管理(FactoryBean)
          • 普通Bean
            • 创建MyBean类
            • 在Spring中配置
            • 新建测试类
            • 执行结果
          • 工厂Bean
            • 修改MyBean
            • 测试
            • 修改测试类
            • 执行结果
        • IOC操作Bean管理(Bean的作用域)
          • Bean的默认作用域
            • 新建测试类
            • 执行结果
          • 设置Bean的作用域
            • 修改Spring配置
            • 使用Test4测试
            • 执行结果
        • IOC操作Bean管理(Bean的生命周期)
          • 生命周期
            • Bean的生命周期
              • 生命周期样例
                • 新建Orders类
                • 在Spring中配置
                • 新建测试类
                • 执行结果
              • Bean的后置处理器
                • 后置处理器样例
                  • 新建后置处理器Bean
                  • 在Spring中进行配置
                  • 测试
                  • 执行结果
              • IOC操作Bean管理(XML自动装配)
                • 什么是自动装配
                  • 演示自动装配过程
                    • 根据属性名称自动注入
                    • 根据类型自动注入
                • IOC操作Bean管理(外部属性文件)
                  • 直接配置数据库信息
                    • 引入德鲁伊连接池的包
                  • 引入外部属性文件配置数据库信息
                    • 创建外部属性文件
                    • 引入Context命名空间
                    • 在Spring中进行配置
                • IOC操作Bean管理(基于注解开发)
                  • 什么是注解
                    • Spring针对Bean管理中创建对象提供的注解
                      • 基于注解的方式创建对象
                        • 引入依赖
                        • 开启注解扫描
                        • 创建UserService类
                        • 新建测试类
                        • 执行结果
                      • 开启组件扫描细节配置
                        • 基于注解实现属性注入
                          • @Autowired
                          • @Qualifier
                          • @Resource
                          • @Value
                        • 去除XML,纯注解开发
                          • 创建配置类,取代XML
                          • 新建测试类
                          • 执行结果
                      相关产品与服务
                      容器服务
                      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
                      http://www.vxiaotou.com