Spring框架-IOC

目录

IOC概念和原理

​编辑 Spring提供IOC容器实现的两种方式(两个接口)

IOC操作Bean管理

1.什么是Bean管理

2.IOC基于xml操作Bean管理

1、基于xml方式创建对象

 2、基于xml方式注入属性-使用set方法进行注入

3.基于xml方式注入属性-使用有参数构造

4、IOC操作Bean管理xml注入其他类型属性

4.基于xml方式注入属性-外部注入bean方式注入属性

5.基于xml方式注入属性-内部bean和级联赋值注入属性的方法

6.xml注入集合属性

7.工厂bean-FactoryBean 

 8.bean创建单例和多利

8.、bean生命周期

9.Bean的后置处理器 

10.xml自动装配

11.     IOC操作Bean管理(外部属性文件-数据库)

 基于注解方式操作bean管理

     1、什么是注解

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

​编辑3、基于注解方式实现对象创建

4、基于注解方式实现属性注入

5、基于注解方式实现属性注入

完全注解开发(了解SpringBoot会真正涉及)



Spring框架概述

1.Spring是轻量级的开源的JavaEE框架

2.Spring可以解决企业应用开发的复杂性

3.Spring有两个核心部分

        IOC:控制反转,把创建对象过程交给Spring进行管理

        Aop:面向切片,不修改源代码进行功能增强

4.Spring特点

        方便解耦,简化开发

        Aop编程支持

        方便程序测试

        方便和替他框架进行整合

        方便进行实务操作

        降低API开发难度

5.使用到的jar包

IOC概念和原理

1.什么是IOC

  • 控制反转,把对象创建和对象之间的调用过程,交给Spring管理

           在传统的 Java 应用中,一个类想要调用另一个类中的属性或方法,通常会先在其代码中通过 new Object() 的方式将后者的对象创建出来,然后才能实现属性或方法的调用。为了方便理解和描述,我们可以将前者称为“调用者”,将后者称为“被调用者”。也就是说,调用者掌握着被调用者对象创建的控制权。

但在 Spring 应用中,Java 对象创建的控制权是掌握在 IoC 容器手里的,其大致步骤如下。

  1. 开发人员通过 XML 配置文件、注解、Java 配置类等方式,对 Java 对象进行定义,例如在 XML 配置文件中使用 <bean> 标签、在 Java 类上使用 @Component 注解等。
  2. Spring 启动时,IoC 容器会自动根据对象定义,将这些对象创建并管理起来。这些被 IoC 容器创建并管理的对象被称为 Spring Bean。
  3. 当我们想要使用某个 Bean 时,可以直接从 IoC 容器中获取(例如通过 ApplicationContext 的 getBean() 方法),而不需要手动通过代码(例如 new Obejct() 的方式)创建。


IoC 带来的最大改变不是代码层面的,而是从思想层面上发生了“主从换位”的改变。原本调用者是主动的一方,它想要使用什么资源就会主动出击,自己创建;但在 Spring 应用中,IoC 容器掌握着主动权,调用者则变成了被动的一方,被动的等待 IoC 容器创建它所需要的对象(Bean)。

这个过程在职责层面发生了控制权的反转,把原本调用者通过代码实现的对象的创建,反转给 IoC 容器来帮忙实现,因此我们将这个过程称为 Spring 的“控制反转”。

  • 使用IOC目的:解耦合

2.IoC 的工作原理

在 Java 软件开发过程中,系统中的各个对象之间、各个模块之间、软件系统和硬件系统之间,或多或少都存在一定的耦合关系。

若一个系统的耦合度过高,那么就会造成难以维护的问题,但完全没有耦合的代码几乎无法完成任何工作,这是由于几乎所有的功能都需要代码之间相互协作、相互依赖才能完成。因此我们在程序设计时,所秉承的思想一般都是在不影响系统功能的前提下,最大限度的降低耦合度。

IoC 底层通过工厂模式、Java 的反射机制、XML 解析等技术,将代码的耦合度降低到最低限度,其主要步骤如下。

  1. 在配置文件(例如 Bean.xml)中,对各个对象以及它们之间的依赖关系进行配置;
  2. 我们可以把 IoC 容器当做一个工厂,这个工厂的产品就是 Spring Bean;
  3. 容器启动时会加载并解析这些配置文件,得到对象的基本信息以及它们之间的依赖关系;
  4. IoC 利用 Java 的反射机制,根据类名生成相应的对象(即 Spring Bean),并根据依赖关系将这个对象注入到依赖它的对象中。


由于对象的基本信息、对象之间的依赖关系都是在配置文件中定义的,并没有在代码中紧密耦合,因此即使对象发生改变,我们也只需要在配置文件中进行修改即可,而无须对 Java 代码进行修改,这就是 Spring IoC 实现解耦的原理。

3.结合例子理解IOC的解耦合

        需求:创建一个类的对象并调用它的方法

        原始方法:可以实现,但是耦合度太高了(两个类之间的联系太密切当其中一个类的信息改变,另一个类创建的对象也要跟着改变)

         工厂模式:解耦合,通过工厂模式降低了与UserDao的耦合度

        但并不能降到最低限度。所以引入IOC,可以将耦合度降到最低

IOC过程:IOC思想是基于IOC容器完成的,IOC的容器底层就是对象工厂

 Spring提供IOC容器实现的两种方式(两个接口)

        1.BeanFactory:IOC容器基本实现,是Spring内部使用的接口,不提供给开发人员使用,获取对象时创见对象

        2.ApplicationContext:BeanFactory的子接口,提供更多更强大的的功能,一般由开发人员进行使用,加载配置文件时就会把配置文件对象进行创建。

        3.ApplicationContext有两个实现类

                ClassPathXmlApplicationContext:是src路径下的文件直接传文件名和后缀即可,加载类路径 ClassPath 下指定的 XML 配置文件,并完成 ApplicationContext 的实例化工作

                FileSystemXmlApplicationContext:是盘下具体的一个文件,要把路径写清楚.加载指定的文件系统路径中指定的 XML 配置文件,并完成 ApplicationContext 的实例化工作

IOC操作Bean管理(依赖注入)

1.什么是Bean管理

      Bean管理是两个操作:Spring创建对象和注入属性

在了解了 IoC 之后,我们还需要了解另外一个非常重要的概念:依赖注入。

依赖注入(Denpendency Injection,简写为 DI)是 Martin Fowler 在 2004 年在对“控制反转”进行解释时提出的。Martin Fowler 认为“控制反转”一词很晦涩,无法让人很直接的理解“到底是哪里反转了”,因此他建议使用“依赖注入”来代替“控制反转”。

在面向对象中,对象和对象之间是存在一种叫做“依赖”的关系。简单来说,依赖关系就是在一个对象中需要用到另外一个对象,即对象中存在一个属性,该属性是另外一个类的对象。

例如,有一个名为 B 的 Java 类,它的代码如下。

public class B {
    String bid;
    A a;
}

从代码可以看出,B 中存在一个 A 类型的对象属性 a,此时我们就可以说 B 的对象依赖于对象 a。而依赖注入就是就是基于这种“依赖关系”而产生的。

我们知道,控制反转核心思想就是由 Spring 负责对象的创建。在对象创建过程中,Spring 会自动根据依赖关系,将它依赖的对象注入到当前对象中,这就是所谓的“依赖注入”。

2.IOC基于xml操作Bean管理

1、基于xml方式创建对象


          <!--配置User对象创建-->
          <bean id=user class="comatguiguspring5.User"></bean>
         (1)在spring配置文件中,使用bean标签,标签里面添加对应属性,就可以实现对象创建
         (2)在bean标签有很多属性,介绍常用的属性
                 id属性:唯一标识
                 class属性:类全路径(包类路径)
         (3)创建对象时候,默认也是执行无参数构造方法完成对象创建

 2、基于xml方式注入属性-使用set方法进行注入


 (1)DI:依赖注入,就是注入属性
        第一种注入方式:使用set方法进行注入

第一步:创建类:定义属性和对应的set方法

public class Class02 {
//    创建属性
    private String bname;
    private  String bauthor;

//    创建属性对应的set方法
    public void setBname(String bname){
        this.bname = bname;
    }
    public void setBauthor(String bauthor){
        this.bauthor = bauthor;
    }
    public void testDemo(){
        System.out.println(bname +","+bauthor);
    }
}

第二步:在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 = "book" class="com.java.spring5.Class02">
    <!--使用property完成属性注入
        name:类里面的属性名称
            value:向属性注入值-->
    <property name="bname" value="诗经"></property>
    <property name="bauthor" value="三国演义"></property>

</bean>
</beans>

第三步:测试

public class Test02 {
    @Test
    public void testadd2(){
//        加载配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
//        获取配置的创建
        Class02 book = context.getBean("book",Class02.class);
        System.out.println(book);
        book.testDemo();
    }
}

3.基于xml方式注入属性-使用有参数构造

        第一步:创建类:定义属性,创建属性对应有参数的构造方法

public class Class03 {
    private String name1;
    private  String bauthor1;

    public Class03(String name1,String bauthor1){
        this.bauthor1 = bauthor1;
        this.name1 = name1;
    }
//    使用有参构造器进行注入
    public void testadd3(){
        System.out.println(name1 +","+ bauthor1);
    }
}

第二步:在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 = "book3" class="com.java.spring5.Class03">
<!--constructor-arg:完成有参注入-->

    <constructor-arg name="name1" value="活着"></constructor-arg>
    <constructor-arg name="bauthor1" value="烟草"></constructor-arg>

</bean>
</beans>

第三步:测试

public class Test03 {
    @Test
    public void testaddd(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
        Class03 book3 = context.getBean("book3",Class03.class);
        System.out.println(book3);
        book3.testadd3();
    }
}

4、IOC操作Bean管理xml注入其他类型属性

(1)null值

<property name = "address><null/></property>

 (2)属性值包含特殊符号

   1把<>进行转义&lt: &gt:
    2把带特殊符号内容写到CDATA
 

  <property name="address"
    <value><![CDATA[<<南京>>]]value></property> 

4.基于xml方式注入属性-外部注入bean方式注入属性

1)创建两个类service类和dao类

  •         创建userDao属性并创建他的set方法

(2)在service调用dao里面的方法        

        在配置文件中创建service对象

        创建userdao的对象

        注入UserDao的属性

(3)在spring配置文件中进行配置。

public class UserService 
   //创建UserDao类型属性,生成set方法
   private UserDao userDao:

   public void setuserDao (UserDao userDao) {
       this. userDao = userDao:
}
   public void add( 
       System.out println(service add)
}
<?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="userService" class="com.java.spring5.service.UserService">
    <!--注入UserDao的属性
        name属性:类里面的属性名称
        ref:创建userDao对象的bean标签,和下边的name值相同-->
<property name="userDao" ref="userdao"></property>
</bean>
    <bean id="userdao" class="com.java.spring5.dao.UserDaoEmp"></bean>
</beans>

5.基于xml方式注入属性-内部bean和级联赋值注入属性的方法

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

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

(3)在spring中配置

(4)测试

内部bean

//员工类
public class Emp {
    private Dept dept;

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

    @Override
    public String toString() {
        return "Emp{" +
                "dept=" + dept +
                '}';
    }
    public void test(){
        System.out.println(dept);
    }
}


//部门类
public class Dept {
    @Override
    public String toString() {
        return "Dept{}";
    }
}
<?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-->
    <bean id="emp" class="com.java.spring5.bean.Emp">
<!--    设置两个普通属性-->
    <property name="ename" value="lucy"></property>
    <property name="gender" value="女"></property>
<!--    设置对象类型属性-->
        <property name="dept" >
            <bean id="dept" class="com.java.spring5.bean.Dept">
                <property name="dname" value="安保部"></property>
            </bean>
        </property>
</bean>
</beans>

 级联赋值的两种写法

1

<?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.java.spring5.bean.Emp">
        <!--    设置两个普通属性-->
        <property name="ename" value="lucy"></property>
        <property name="gender" value="女"></property>
<!--       级联赋值-->
<property name="dept" ref="dept1" ></property>
    </bean>
    <bean id="dept1" class="com.java.spring5.bean.Dept">
        <property name="dname" value="财务部"></property>

    </bean>
</beans>

        输出:lucy 女 财务部

2

<?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.java.spring5.bean.Emp">
        <!--    设置两个普通属性-->
        <property name="ename" value="lucy"></property>
        <property name="gender" value="女"></property>
        <!--       级联赋值-->
        <property name="dept" ref="dept1" ></property>
<!--        Emp类里有两个字符串属性,一个对象属性,对象属性中的Dept里有一个属性dname,
            调用它在这里就可以给他赋值,但不能直接调用,要现在Emp中得到这个对象,及生成dept属性的get方法-->
        <property name="dept.dname" value="技术部"></property>
    </bean>
    <bean id="dept1" class="com.java.spring5.bean.Dept">
        <property name="dname" value="财务部"></property>

    </bean>
</beans>

6.xml注入集合属性

  • 注入数组类型属性
  • 注入List集合属性
  • 注入Map集合类型
  • 注入 set集合

        第一步:创建类,定义数组、list、map、set类型属性,生成对应的set方法

public class Stu {
//    数组类型属性
    private String[] courses;


//    List集合类型属性
    private List<String> list;



//    Map集合类型shuxing
    private Map<String,String> maps;



//    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;
    }
    public void test(){
        System.out.println(Arrays.toString(courses));
        System.out.println(list);
        System.out.println(maps);
        System.out.println(sets);
        System.out.println(courseList);
    }
}



public class Course {
    private String cname;

    public void setCname(String cname) {
        this.cname = cname;
    }

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

        第二步:在spring配置文件进行配置

  •  数组类型属性注入 标签array
  •  list属性注入  标签list
  • Map属性注入 标签map、 entry
  • set属性注入 标签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="stu" class="com.java.spring5.collectiontype.Stu">
<!--    数组类型属性注入 标签array-->
    <property name="courses">
        <array>
            <value>java</value>
            <value>数据库</value>
        </array>
    </property>
<!--    list属性注入  标签list-->
    <property name="list">
        <list>
            <value>张三</value>
            <value>李四</value>
        </list>

    </property>
<!--    Map属性注入  标签map entry---->
<property name="maps">
    <map>
        <entry key="JAVA" value="java"></entry>
        <entry key="PHP" value="php"></entry>
    </map>
</property>
<!--    set属性注入  标签set-->
    <property name="sets">
        <set>
            <value>mysql</value>
            <value>redies</value>
        </set>
    </property>
</bean>

</beans>

测试

public class Testc1 {
    @Test
    public void testCollectin1(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beanc1.xml");
        Stu stu = context.getBean("stu", Stu.class);
        stu.test();

    }
}

但集合属性要考虑两个细节

第一个细节:刚刚创建的都是String属性,如果我想在集合理放对象怎么放

第二个细节:上述集合只能在id=stu中使用,不能再其他部分适用,如何提取集合将他变成公共部分

第一个细节(list为例)

 (1)创建多个对象,和上述第一步创建内容一样

 (2)注入属性

<?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">
<!--注入list集合类型-->
    <bean id="cou" class="com.java.spring5.collectiontype.Stu">

        <property name="courseList">
            <list>
<!--                不是注入普通值,注入对象值标签ref-->
                <ref bean="course1"></ref>
                <ref bean="course2"></ref>
            </list>
        </property>
    </bean>
    <bean id="course1" class="com.java.spring5.collectiontype.Course">
        <property name="cname" value="Spring5"></property>
    </bean>
    <bean id="course2" class="com.java.spring5.collectiontype.Course">
        <property name="cname" value="Mybatis"></property>
    </bean>
</beans>

(3)测试

public class Testc2 {
    @Test
    public  void testCollection2(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beanc2.xml");
        Stu stu = context.getBean("cou",Stu.class);
        stu.test();
    }
}

 

第二个细节

(1)创建多个对象,和上述第一步创建内容一样

 (2)创建提取类book

//提取类
public class Book {
    private List<String> list;

    public void setList(List<String> list) {
        this.list = list;
    }

    @Override
    public String toString() {
        return "Book{" +
                "list=" + list +
                '}';
    }
    public void test3(){
        System.out.println(list);
    }
}

 (3)在spring配置文件中引入名称空间util(注意上面xmlns和xsi配置)

<?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"
       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">
<!--提取list集合类型属性注入-->
    <util:list id="bookList">
    <value>诗</value>
    <value>词</value>
    <value>歌</value>
</util:list>

<!--    提取list集合类型属性注入-->
    <bean id="book" class="com.java.spring5.collectiontype.Book">
        <property name="list" ref="bookList"></property>
    </bean>
</beans>

(4)测试

public class Testc3 {

        @Test
        public void testCollectin3(){
            ApplicationContext context = new ClassPathXmlApplicationContext("beanc3.xml");
           Book bo = context.getBean("book", Book.class);
            bo.test3();

        }
}

7.工厂bean-FactoryBean 


       1、Spring有两种类型bean,一种普通bean,另外一种工厂bean-FactoryBean 
        2、普通bean:在配置文件中定义bean类型就是返回类型(上面的就是普通的)
        3、工厂bean:在配置文件定义bean类型可以和返回类型不一样
             第一步创建类,让这个类作为工厂bean,实现接口FactoryBean 

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

//实现factorybean实现接口
public class MyBean implements FactoryBean<Course> {
//返回类型方法,你定义的类型和返回类型不一样是由此方法决定
//    类里定义的是MyBean类型,返回Course类型
    @Override
    public Course getObject() throws Exception {
        Course course = new Course();
        course.setCname("abc");
        return course;
    }
//返回类型
    @Override
    public Class<?> getObjectType() {
        return null;
    }
//是否是一个单例
//单例:所有请求都有一个对象来处理,因为没必要每个请求都建一个对象
    @Override
    public boolean isSingleton() {
        return FactoryBean.super.isSingleton();
    }
}
<?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="mybean" class="com.java.spring5.factorybean.MyBean"></bean>
</beans>
public class Testf1 {

        @Test
        public void testf1(){
            ApplicationContext context = new ClassPathXmlApplicationContext("beanf.xml");
//         注意.class调用的类名,是返回值的类型
            Course mybean = context.getBean("mybean", Course.class);
            System.out.println(mybean);


        }
}

 8.bean创建单例和多利

在Spring里,默认情况下,bean是单例

         Book1和 Book2输出内容相同

如何设置单例还是多例
(1)在spring配置文件bean标签里面有属性(scope)用于设置单实例还是多实例
(2)scope属性值
第一个值默认值,singleton,表示是单实例对象
第二个值prototype,表示是多实例对象

singleton和prototype区别
第一 singleton单实例,prototype多实例
第二设置scope值是singleton时候,加载spring配置文件时候就会创建单实例对象+
       设置scope值是prototype时候,不是在加载spring配置文件时候创建对象,在调用getBean方法时候创建多实例对象 

8.、bean生命周期

生命周期
 (1)从对象创建到对象销毁的过程
 2、bean生命周期,无后置配置处理器时
 (1)通过构造器创建bean实例(无参数构造)
 (2)为bean的属性设置值和对其他bean引用(调用set方法)
  (3)调用bean的初始化的方法(需要进行配置初始化的方法)
  (4)bean可以使用了(对象获取到了)
  (5)当容器关闭时候,词用bean的销毁的方法(需要进行配置销毁的方法)

public class Orders {
    private  String oname;

    public Orders() {
        System.out.println("第一步:执行无参构造器创建bean实例");
    }

    public void setOname(String oname) {
        this.oname = oname;
        System.out.println("第二步:调用set方法设置属性值");
    }
//    创建执行初始化的方法,但这只是一个普通的方法不会自己执行所以我们要进行配置
    public void initMethod(){
        System.out.println("执行初始化的方法");
    }
//    销毁方法
    public void destory(){
        System.out.println("第五步:这是一个销毁方法");
    }
}
<?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">

<!--    init-method:方法名字:配置初始化方法
        destory-method:方法名字:执行销毁方法-->
<bean id="orders" class="com.java.spring5.bean.Orders" init-method="initMethod" destroy-method="destory">
    <property name="oname" value="手机"></property>
</bean>

</beans>
public class Testl1 {
    @Test
    public void life(){
//        ApplicationContext不能调用close方法他的子类可以ClassPathXmlApplicationContext
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beanl1.xml");
        Orders orders = context.getBean("orders", Orders.class);
        System.out.println("第四步:获取创建bean实例对象");
        System.out.println(orders);

//        手动销毁bean实例才能让配置调用
context.close();

    }

9.Bean的后置处理器 

bean有后置处理器,bean生命周期有七步
 (1)通过构造器创建bean实例(无参数构造)
 ( 2)为bean的属性设置值和对其他bean引用(调用set方法)t
 (3)把bean实例传递bean后置处理器的方法postProessAfternitialization

 (4)调用bean的初始化的方法(需要进行配置初始化的方法)
(5))把bean实例传递bean后置处理器的方法postProessAfternitialization
(6)bean可以使用了(对象获取到了)
(7)当容器关闭时候,调用bean的销毁的方法(需要进行配置销毁的方法)
演示添加后置处理器效果
1)创建类,实现接口BeanPostProessor 创建后置处理器

public class Orders {
    private  String oname;

    public Orders() {
        System.out.println("第一步:执行无参构造器创建bean实例");
    }

    public void setOname(String oname) {
        this.oname = oname;
        System.out.println("第二步:调用set方法设置属性值");
    }
//    创建执行初始化的方法,但这只是一个普通的方法不会自己执行所以我们要进行配置
    public void initMethod(){
        System.out.println("执行初始化的方法");
    }
//    销毁方法
    public void destory(){
        System.out.println("第五步:这是一个销毁方法");
    }
}





public class MyBeanFost implements BeanPostProcessor {

        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("这是初始化之前执行的方法");
            return bean;
        }

        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("这是初始化之后执行的方法");
            return 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">

<!--    init-method:方法名字:配置初始化方法
        destory-method:方法名字:执行销毁方法-->
<bean id="orders" class="com.java.spring5.bean.Orders" init-method="initMethod" destroy-method="destory">
    <property name="oname" value="手机"></property>
</bean>
<!--    配置后置处理器,会给上边创建的所有bean实例配置后置处理器-->
<!--    应为实现了接口,spring就会把他当做后置处理器执行-->
    <bean id="myBeanPost" class="com.java.spring5.bean.MyBeanFost"></bean>
</beans>
public class Testl1 {
    @Test
    public void life(){
//        ApplicationContext不能调用close方法他的子类可以ClassPathXmlApplicationContext
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beanl1.xml");
        Orders orders = context.getBean("orders", Orders.class);
        System.out.println("第四步:获取创建bean实例对象");
        System.out.println(orders);

//        手动销毁bean实例才能让配置调用
context.close();

    }

 

10.xml自动装配

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

根据属性名或类型自动注入 

 第一步:创建类和属性

public class Emp {

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

    @Override
    public String toString() {
        return "Emp{" +
                "dept=" + dept +
                '}';
    }
    public void test(){
        System.out.println(dept);
    }
}




public class Dept {
    @Override
    public String toString() {
        return "Dept{}";
    }
}

 第二步:配置xml属性

 实现自动装配
        bean标签属性autowire实现自动装配
        这个属性有两个值:byName根据属性名称注入,注入bean的值必须和类的属性名称一样
        byType:根据属性类型注入,同一个类型只能注册一次

<?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标签属性autowire实现自动装配
        这个属性有两个值:byName根据属性名称注入,注入bean的值必须和类的属性名称一样
          byType:根据属性类型注入,同一个类型只能注册一次-->
    <bean id="emp" class="com.java.spring5.autowire.Emp" autowire="byName">
<!-- 手动注入   <property name="dept" ref="dept1"></property>-->
</bean>
<!--    注入bean的值必须和类的属性名称一样-->
    <bean id="dept" class="com.java.spring5.autowire.Dept"  ></bean>
<!--    再加上下面那句,使用bytype就会报错,因为和上面的bean是同一个类型(Dept),但byname不会-->
<!--    <bean id="dept1" class="com.java.spring5.autowire.Dept"></bean>-->
</beans>

11.     IOC操作Bean管理(外部属性文件-数据库)


          1、直接配置数据库信息
                1)配置德鲁伊连接池
                 2)引入德鲁伊连接池依赖jar包

               2.引入外部属性文件配置数据库连接池

                1)创建外部属性文件,properties格式文件,写数据库信息

prop.driverClass=com.mysql.cj.jdbc.Driver
prop.url=jdbc:mysql://localhost:3306/test
prop.name=root
prop.password=123456

                2)把外部properties属性文件引入到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:context="http://www.springframework.org/schema/context"
       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
                            http://www.springframework.org/schema/context http://www.springframework.org/schema/beans/spring-context.xsd">
<bean id="dtaSocutse" class="com.alibaba.druid.pool.DruidDataSource">
<!--直接配置未使用配置文件-->
    <!--    固定的值:driverClassName驱动名称,
                url:数据库地址-->
<!--    <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>-->
<!--    <property name="url" value="jdbc:mysql://localhost:3306/test"></property>-->
<!--    <property name="username" value="root"></property>-->
<!--    <property name="password" value="123456"></property>-->
<!--    配置文件配置连接池-->
    <property name="driverClassName" value="${prop.driverClass"></property>
    <property name="url" value="${prop.url"></property>
    <property name="username" value="${prop.name"></property>
    <property name="password" value="${prop.password"></property>


</bean>
</beans>

 基于注解方式操作bean管理

     1、什么是注解


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


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


         1)@Component:普通组建利用它都可以创建对象
          2)@Service:一般用在业务逻辑和service层
          3)@Controllei:用在web层
         4)@Repository:dao层

四者使用时没什么区别,都是用来创建对象的且参数都为value,value为此bean的名字可不写,默认为第一个字母为小写的类名


3、基于注解方式实现对象创建


第一步引入依赖

第二步开启组件扫描

context:component-scan:关键字扫描

base-package:要扫描的包名
   如果扫多个包,多个包使用号隔开  或扫描包上层目录

<context:component-scan base-package="com.java.spring5"></context:component-scan>

第三步创建类,在类上面添加创建对象注解
 在注解里面value属性值可以省略不写,
 默认值是类名称,首字母小写

<?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:context="http://www.springframework.org/schema/context"
       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
                            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--    开启组件扫描
        如果扫描多个,多个包使用逗号隔开
           或扫描包的上层目录-->
    <context:component-scan base-package="com.java.spring5"></context:component-scan>


</beans>
//使用注解创建对象可使用四个注解中任何一个
//在注解里面的value可以省略不写,他会默认类名的首字母小写

@Service(value = "userService")

public class UserService {

//    定义dao属性不需要添加set方法,添加属性注解即可

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


}

 测试

public class TestZhujie {
    @Test
    public void testServices(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beanzhu1.xml");
//        这里不在是id值,因为value值相当于id值
        UserService userService = context.getBean("userService", UserService.class);
        System.out.println(userService);
        userService.add();
    }
}

 细节:扫描类的选择

红色:扫描包中的所有类

彩色:扫描Controller注解中的所有类

 

其中type有annotation,aspectj,assignable,custom,regex几种类型。

其意义如下: 

annotation:注解类型
assignable_type:annotation:指定的类型
aspectj:按照Aspectj的表达式,基本上不会用到
regex:按照正则表达式
custom:自定义规则

4、基于注解方式实现属性注入

(1)@Autowired:根据属性类型进行自动装配
 (2)@Qualifier:根据属性名称进行注入
 (3) @Resource: 可以根据类型注入,可以根据名称注入
  (4) @value:注入普通类型属性

5、基于注解方式实现属性注入

(1)@Autoired根据属性类型进行自动装配
第一步service和dao对象创建,在senvice和dao类添加创建对象注解(@Service @Repository )

第二步在service注入da0对象,在sevice类添加dao类型属性,在属性上面使用注解(   @Autowired)

@Service
public class UserService {

//    定义接口属性,不需要添加set方法,添加注入属性注解
    @Autowired
    private UserDao userDao;
    public void add(){
        System.out.println("service add...");
        userDao.add1();
    }
}



public interface UserDao {
    public void add1();
}

@Repository
public class UserDaoEmp1 implements UserDao {
    @Override
    public void add1() {
        System.out.println("dao");
    }
}

测试

public class Test1 {
    @Test

    public void testServices(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
//        这里不在是id值,因为value值相当于id值
        UserService userService = context.getBean("userService", UserService.class);
        System.out.println(userService);
        userService.add();
    }

}

 (2)@Qualifier:根据属性名称进行注入(但必须结合@Autowired使用)

         当有多个接口实现类时Autowired没有办法确定是哪个实现类。所以结合@Qualifier根据名称进行注解

(3)  @Resource: 可以根据类型注入,可以根据名称注入

 

 4) @value:注入普通类型属性


       输出:   name = abc 

完全注解开发(了解SpringBoot会真正涉及)

        

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值