一、Spring框架概述

  1. Spring框架是轻量级的开源的JavaEE框架
  2. Spring框架可以解决企业应用开发的复杂性
  3. Spring框架有两个核心部分:IOC和AOP
  4. Spring框架特点:方便解耦,简化开发;AOP编程支持;方便程序测试;方便和其它框架进行整合;方便事务事务操作;降低API开发难度

IOC概念和原理

1、什么是IOC?

  1. 控制反转,把对象创建和对象之间的调用过程交给Spring框架进行管理
  2. 使用IOC的目的:为了耦合度降低
  3. 做入门案例就是IOC实现

2、IOC底层原理

xml解析——XML有三种解析方式:DOM SAX STAX

存储和传输数据经常一起使用,XML数据通常由程序生成的,用程序解析XML(XML一般不加约束)

 配置文件单独使用(通常会加约束)

工厂模式——把对类的创建初始化全都交给一个工厂来执行,而用户不需要去关心创建的过程是什么样的

反射 ——反射可以在运行时根据指定的类名获得类的信息

3、IOC底层原理的图形解析

第一种图解方式:

第二种图解方式(为了避免第一种创建过程中存在耦合度比较高的情况,使用IOC进行创建):

4、IOC接口

  1. IOC思想是基于IOC容器完成,IOC容器底层就是对象工厂
  2. Spring框架中对IOC容器实现提供了两种方式(即两种接口)

         2.1 第一种接口(BeanFactory接口):此接口是IOC容器的基本实现,也是Spring框架内部使用的接口,不提供给开发人员进行使用

注:此接口是在加载配置文件时不会创建对象,而是在获取对象或使用时才去创建对象

        2.2 第二个接口(ApplicationContext):此接口是BeanFactory接口的子接口,提供了更强大的功能,一般由开发人员进行

注:此接口在加载配置文件时就会创建配置文件中所配置的对象

5、ApplicationContext接口的所有实现类

6、IOC操作Bean管理(基于xml配置文件方式实现Spring框架中创建对象和注入属性)

6.1 Spring框架中对象的创建

第一步:基于xml方式创建对象

<!--创建对象-->
<bean id="stu" class="com.spring.collection.Stu"><bean/>
  1. 在Spring框架配置文件中,使用bean标签,标签里面添加对应属性,就可以实现对象的创建
  2. 在bean标签中有很多属性,常用的属性介绍:id属性——唯一标识   class属性——类全路径
  3. 创建对象时默认执行无参构造方法完成对象的创建

6.2 Spring框架中对一个对象中的属性进行注入

介绍注入属性之前,先介绍一下DI——就是依赖注入,也是属性注入

第一种注入的方式使用set方法进行注入

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

/** 
* 演示使用set方法进行注入属性 
*/ 
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; 
    } 
}

第二步:在Spring配置文件中创建对象,然后配置属性注入

<!--2 set方法注入属性--> 
<bean id="book" class="com.spring5.Book">
    <!--使用property完成属性注入 name:类里面属性名称 value:向属性注入的值 --> 
    <property name="bname" value="易筋经"></property> 
    <property name="bauthor" value="达摩老祖"></property> 
</bean>

第二种属性注入方式:使用有参构造进行注入

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

/** 
* 使用有参数构造注入
*/ 
public class Orders { 
    //属性 
    private String oname; 
    private String address; 
    //有参数构造 
    public Orders(String oname,String address) { 
        this.oname = oname; 
        this.address = address; 
    } 
}

第二步在Spring配置文件中进行配置

<!--3 有参数构造注入属性--> 
<bean id="orders" class="com.spring5.Orders"> 
    <constructor-arg name="oname" value="电脑"></constructor-arg> 
    <constructor-arg name="address" value="China"></constructor-arg> 
</bean>

第三种注入方式是引入p名称空间进行属性的注入

第一步:在配置文件中添加p名称空间

第二步进行属性注入

<!--2 set方法注入属性--> 
<bean id="book" class="com.atguigu.spring5.Book" p:bname="九阳神功" p:bauthor="无名氏"></bean>

第四种是其它类型属性的注入

第一种是null值的注入

<!--null值--> 
<property name="address"> 
    <null/> 
</property>

第二种是属性值包含特殊符号

<!--属性值包含特殊符号 
1 把<>进行转义 &lt; &gt; 
2 把带特殊符号内容写到CDATA 
--> 
<property name="address"> 
    <value><![CDATA[<<南京>>]]></value> 
</property>

第三种是对象的注入(外部bean)

public class UserService { 
    //创建UserDao类型属性,生成set方法 private UserDao userDao; 
    public void setUserDao(UserDao userDao) { 
        this.userDao = userDao; 
    } 
    public void add() { 
        System.out.println("service add..............."); 
        userDao.update(); 
    } 
}
<!--1 service和dao对象创建--> 
<bean id="userService" class="com.spring5.service.UserService"> 
    <!--注入userDao对象 name属性:类里面属性名称 ref属性:创建userDao对象bean标签id值 --> 
    <property name="userDao" ref="userDaoImpl"></property> 
</bean> 
<bean id="userDaoImpl" class="com.atguigu.spring5.dao.UserDaoImpl"></bean>

第四种对象的注入(内部)

//部门类 
public class Dept { 
    private String dname; 
    public void setDname(String dname) { 
        this.dname = dname; 
    } 
} 

//员工类 
class Emp { 
    private String ename; 
    private String gender; 
    //员工属于某一个部门,使用对象形式表示 
    private Dept dept; 
    public void setDept(Dept dept) { 
        this.dept = dept; 
    } 
    public void setEname(String ename) { 
        this.ename = ename; 
    } 
    public void setGender(String gender) { 
        this.gender = gender;
    } 
}
<!--内部bean--> 
<bean id="emp" class="com.atguigu.spring5.bean.Emp"> 
    <!--设置两个普通属性--> 
    <property name="ename" value="lucy"></property> 
    <property name="gender" value="女"></property> 
    <!--设置对象类型属性--> 
    <property name="dept"> 
        <bean id="dept" class="com.atguigu.spring5.bean.Dept"> 
            <property name="dname" value="安保部"></property> 
        </bean> 
    </property>
</bean>

第五种集合的注入

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

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

    //3 map集合类型属性 
    private Map<String,String> maps; 

    //4 set集合类型属性 
    private Set<String> sets; 

    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; 
    } 
}
<bean id="stu" class="com.spring.collection.Stu">
        <property name="courses">
            <array>
                <value>java课程01</value>
                <value>java课程02</value>
            </array>
        </property>
        <property name="list">
            <list>
                <value>张三</value>
                <value>李四</value>
            </list>
        </property>
        <property name="map">
            <map>
                <entry key="JAVA" value="java"></entry>
                <entry key="PHP" value="php"></entry>
            </map>
        </property>
        <property name="sets">
            <set>
                <value>MySql</value>
                <value>Web</value>
            </set>
        </property>

<!--        注入一个集合类型中存放的是对象-->
        <property name="courseList">
            <list>
                <ref bean="course_01"></ref>
                <ref bean="course_02"></ref>
            </list>
        </property>
    </bean>

<!--    创建多个course对象-->
    <bean id="course_01" class="com.spring.collection.Course">
        <property name="cName" value="MyBatis"></property>
    </bean>
    <bean id="course_02" class="com.spring.collection.Course">
        <property name="cName" value="Spring"></property>
    </bean>

6.3 bean的作用域

  1. 在Spring里面,设置创建bean实例是单实例还是多实例
  2. 在Spring里面,默认情况下,bean是单实例
 @Test
    public void test01(){
        ApplicationContext context = new ClassPathXmlApplicationContext(
                "bean_01.xml");
        Stu stu1 = context.getBean("stu", Stu.class);
        Stu stu2 = context.getBean("stu", Stu.class);
        System.out.println(stu1);
        System.out.println(stu2);
    }

如何设置多实例?

  1. 在Spring配置文件bean标签中有属性scope用于设置单实例还是多实例
  2. 默认值——singleton(单实例)  prototype(多实例)

单实例和多实例的区别?

  • 单实例是在加载Spring配置文件时候就会创建单实例对象
  • 多实例不是在加载配置文件时创建对象,而是在调用getBean方法时创建对象

6.4 bean的生命周期

  1. 生命周期——指对象从创建到销毁的过程
  2. bean的生命周期
  • 通过构造器创建bean实例(无参构造)
  • 为bean的属性设置值和对其他bean引用(使用set方式注入)
  • 调用bean的初始化方法(需要配置)
  • 获取bean对象
  • 当容器关闭时,销毁(需要配置)
public class Orders {
    //无参数构造 
    public Orders() { 
        System.out.println("第一步 执行无参数构造创建bean实例"); 
    } 
    private String oname; 
    public void setOname(String oname) { 
        this.oname = oname; 
        System.out.println("第二步 调用set方法设置属性值"); 
    } 
    //创建执行的初始化的方法 
    public void initMethod() { 
        System.out.println("第三步 执行初始化的方法"); 
    } 
    //创建执行的销毁的方法 
    public void destroyMethod() { 
        System.out.println("第五步 执行销毁的方法"); 
    } 
}

<bean id="orders" class="com.atguigu.spring5.bean.Orders" init-method="initMethod" destroy-method="destroyMethod"> 
    <property name="oname" value="手机"></property> 
</bean>

@Test 
public void testBean3() { 
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml"); Orders orders = context.getBean("orders", Orders.class); 
    System.out.println("第四步 获取创建bean实例对象"); 
    System.out.println(orders); 
    //手动让bean实例销毁 
    context.close(); 
}

7、基于注解实现IOC操作Bean管理

7.1 什么是注解?

  1. 注解是代码的特殊标记,格式形如(属性名称=属性值....)
  2. 使用注解,注解可作用在类上面,方法上面,属性上面

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

  1. @Commponent
  2. @Service——一般使用在Service层
  3. @Controller——一般使用在Web层
  4. Repository——一般使用在Dao层

第一步:引入依赖

第二步:开启组件扫描

<!--开启组件扫描 1 如果扫描多个包,多个包使用逗号隔开 2 扫描包上层目录 --> 
<context:component-scan base-package="com.atguigu"></context:component-scan>

第三步:创建类,在类上面添加创建对象注解

//在注解里面value属性值可以省略不写, 
//默认值是类名称,首字母小写 
//UserService -- userService
@Component(value = "userService") //<bean id="userService" class=".."/> 
public class UserService { 
    public void add() { 
        System.out.println("service add......."); 
    } 
}

7.3 使用注解方式实现属性的注入

@Autowired:根据属性类型进行自动装配

@Service 
public class UserService { 
    //定义dao类型属性 
    //不需要添加set方法
    //添加注入属性注解 
    @Autowired 
    private UserDao userDao; 
    public void add() { 
        System.out.println("service add......."); 
        userDao.add(); 
    } 
}

@Qualifier:根据名称进行注入
这个@Qualifier注解的使用,和上面@Autowired一起使用 

//定义dao类型属性 
//不需要添加set方法
//添加注入属性注解 
@Autowired 
//根据类型进行注入 因为userDao接口的实现类可以有很多个
@Qualifier(value = "userDaoImpl1") 
//根据名称进行注入 
private UserDao userDao;

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

//@Resource //根据类型进行注入 
@Resource(name = "userDaoImpl1") 
//根据名称进行注入 
private UserDao userDao;

@Value:注入普通类型属性

@Value(value = "abc") 
private String name;

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐