Spring5框架——IOC和DI

目录

Spring框架概述

1. Spring简介

2. Spring 特点

3. Spring的体系结构

4. Spring快速入门

 IOC容器

1. IOC底层原理

2. Bean管理

2.1 Bean标签基本配置

2.2 Bean实例化三种方式

2.3 bean作用域和生命周期

3. 依赖注入 DI

3.1 基于xml方式的注入

3.1 基于注解方式的注入

4. IOC接口(BeanFactory)


Spring框架概述

1. Spring简介

1、Spring是分层的Java SE/EE应用 full-stack(全栈)轻量开源框架,以IOCAOP为内核。

      轻量:依赖的jar包数量少,体量小  开源:免费提供源代码  全栈:各层都有对应的解决方案

2、Spring框架可以解决企业应用开发的复杂性。Spring提供了展现层 SpringMVC 和持久层 Spring JDBCTemplate 以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的Java EE 企业应用开源框架。

3、Spring有两个核心部分:IOC和AOP

        (1)IOC(Inversion of Control):控制反转,把创建对象过程交给 Spring 进行管理

        (2)Aop(Aspect Orient Programming):面向切面编程,不修改源代码进行功能增强

2. Spring 特点

(1)方便解耦,简化开发

        通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。

(2)Aop 编程支持

        通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应付

(3)方便程序测试

        可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作,而是随手可做的事情。

(4)方便和其他框架进行整合

        Spring对各种优秀框架(Struts、Hibernate、Hessian、Quartz等)的支持。

(5)方便进行事务操作

        在Spring中,我们可以从单调烦闷的事务管理代码中(编程式)解脱出来,通过声明式方式灵活地进行事务的管理

(6)降低 API 开发难度

        Spring对很多难用的Java EE API(如JDBC,JavaMail,远程调用等)提供了一个薄薄的封装层,通过Spring的简易封装,这些Java EE API的使用难度大为降低

(7)Java 源码是经典学习范例

Spring的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对Java 设计模式灵活运用以及对 Java技术的高深造诣。它的源代码无意是 Java 技术的最佳实践的范例。

3. Spring的体系结构

4. Spring快速入门

4.1 Spring程序开发步骤

① 导入 Spring 开发的基本包坐标
② 编写 Dao 接口和实现类
③ 创建 Spring 核心配置文件
④ 在 Spring 配置文件中配置 UserDaoImpl
⑤ 使用 Spring 提供的 API 获得 Bean 实例 

4.2 导入Spring开发的基本包坐标

使用maven:

<properties>
    <spring.version>5.0.5.RELEASE</spring.version>
</properties>
<dependencies>
    <!--导入spring的context坐标,context依赖core、beans、expression-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
</dependencies>

 不使用maven的情况(使用maven的可跳过此部分):

下载Spring5

         SPRING官方网站改版后,建议都是通过 Maven和Gradle下载,对不使用Maven和Gradle开发项目的,载就非常麻烦,下给出Spring Framework jar官方直接下载路径:访问下载地址https://repo.spring.io/release/org/springframework/spring,下载最新版

                对下载完成的spring-5.2.6.RELEASE-dist压缩文件解压

          2.打开idea,创建普通java工程

                file-new proiect

       3.导入spring5的相关jar包(4个spring基本核心jar包+commons-logging.jar(日志包))

4.3 编写Dao接口和实现类

public interface UserDao {
    public void save();
}

public class UserDaoImpl implements UserDao {
    @Override
    public void save() {
        System.out.println("UserDao save method running....");
    }
}

4.4 创建Spring核心配置文件

在类路径下(resources)创建applicationContext.xml配置文件

 idea会自动生成

4.5 在Spring配置文件中配置UserDaoImpl

          bean标签,class类路径,id为给对象的别名         

4.6 使用Spring的API获得Bean实例

@Test
public void testAdd() {
     //1 加载 spring 配置文件
     ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
     //2 获取配置创建的对象
     UserDao userDao = (UserDao)context.getBean("userDao");
     userDao.save();
}

总结:Spring的开发步骤 

① 导入坐标(配置pom)
② 创建Bean的类
③ 创建applicationContext.xml
④ 在配置文件中配置bean
⑤ 创建ApplicationContext对象getBean

 IOC容器

1. IOC底层原理

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

2、IOC 底层原理
(1)xml 解析、工厂模式、反射
原始方式,在一个类中调用另一个类的方法,要先创建该类的对象,然后调用该对象方法。此方式耦合度高。

使用工厂模式,建工厂类,工厂类解析被代理类的xml文件,通过反射创建目标对象。

 xml解析得到Class属性值。反射创建对象。降低了耦合,要改只需要改配置中的属性。  

2. Bean管理

什么是 Bean 管理
         Bean管理指的是两个操作
        (1)Spring 创建对象(实例化)
        (2)Spirng 注入属性(初始化)
2、Bean 管理操作有两种方式
        (1)基于 xml 配置文件方式实现
        (2)基于注解方式实现

2.1 Bean标签基本配置

用于配置对象交由Spring 来创建。

默认情况下它调用的是类中的无参构造函数,如果没有无参构造函数则不能创建成功。

<!--配置User对象创建-->
<bean id="user" class="com.atgui.spring.User"></bean>

基本属性:
id:Bean实例在Spring容器中的唯一标识
class:Bean的全限定名称

2.2 Bean实例化三种方式

无参构造方法实例化
工厂静态方法实例化
工厂实例方法实例化

1) 使用无参构造方法实例化

它会根据默认无参构造方法来创建类对象,如果bean中没有默认无参构造函数,将会创建失败

<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>

2) 工厂静态方法实例化

工厂的静态方法返回Bean实例

public class StaticFactoryBean {
    public static UserDao createUserDao(){
        return new UserDaoImpl();
    }
}
<!--使用工厂的方式-->
<bean id="userDao" class="com.itheima.factory.StaticFactoryBean" factory-method="createUserDao" />

spring解析时发现factory-method,会找此全包名对应的内部属性的方法,返回对应的对象

3) 工厂实例方法实例化

工厂的非静态方法返回Bean实例

public class DynamicFactoryBean {
    public UserDao createUserDao(){
        return new UserDaoImpl();
    }
}
<bean id="factoryBean" class="com.itheima.factory.DynamicFactoryBean"/>
<bean id="userDao" factory-bean="factoryBean" factory-method="createUserDao"/>

通过工厂对象中的方法获取对应的对象

2.3 bean作用域和生命周期

作用域

1、在 Spring 里面,设置创建 bean 实例是单实例还是多实例,这个叫bean的作用域
2、在 Spring 里面,默认情况下,bean 是单实例对象。单实例:只有一个对象,实例对象地址相同,多实例:每次都建新对象,实例对象地址不同

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

 (3)singleton 和 prototype 区别
         1)当scope的取值为singleton时Bean的实例化个数:1个
             Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例
             Bean的生命周期:
             对象创建:当应用加载,创建容器时,对象就被创建了
             对象运行:只要容器在,对象一直活着
             对象销毁:当应用卸载,销毁容器时,对象就被销毁了
        2)当scope的取值为prototype
             Bean的实例化个数:多个
             Bean的实例化时机:当调用getBean()方法时实例化Bean
             对象创建:当使用对象时,创建新的对象实例
             对象运行:只要对象在使用中,就一直活着
             对象销毁:当对象长时间不用时,被 Java 的垃圾回收器回收了

生命周期
        从对象创建到对象销毁的过程

Bean生命周期配置
        init-method:指定类中的初始化方法名称
        destroy-method:指定类中销毁方法名称

演示 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 destroyMethod() {
   System.out.println("第五步 执行销毁的方法");
 }
}
<bean id="orders" class="com.atguigu.spring5.bean.Orders" initmethod="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();//执行此方法后才会调用destoryMethod
 }

其实bean的生命周期还有两步,过程叫bean的后置处理器

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

演示添加后置处理器效果

(1)创建类,实现接口BeanPostProcessor,创建后置处理器

public class MyBeanPost 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;
 }
}
<!--配置后置处理器-->
<bean id="myBeanPost" class="com.atguigu.spring5.bean.MyBeanPost"></bean>

3. 依赖注入 DI

依赖注入(Dependency Injection):依赖注入,就是注入属性。它是 Spring 框架核心IOC 的具体实现。

3.1 基于xml方式的注入

Bean的依赖注入方式

构造方法
set方法

第一种注入方式:使用 set 方法进行注入
(1)创建类,定义属性和对应的 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;
     }
}

(2)在 spring 配置文件配置对象创建,配置属性注入 

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

p名称空间注入(了解)

 P命名空间注入本质也是set方法注入,使用 p 名称空间注入,可以简化基于 xml 配置方式

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

第二步 进行属性注入,在 bean 标签里面进行操作

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

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

(1)创建类,定义属性,创建属性对应有参数构造方法

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

       (2)在 spring 配置文件中进行配置        

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

xml注入其他类型属性

1、字面量(变量的值)
    null 值

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

    属性值包含特殊符号

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

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

2、注入属性-外部bean

<!--1 service 和 dao 对象创建-->
<bean id="userService" class="com.atguigu.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>

ref=外部bean id 

3、注入属性-内部 bean

<!--内部 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>

4、注入属性&级联赋值

第一种写法

<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>
</bean>
<bean id="dept" class="com.atguigu.spring5.bean.Dept">
   <property name="dname" value="财务部"></property>
</bean>

在外部bean的基础上赋值

(2)第二种写法

在emp类中要给dept对象的属性赋值,需要先写获得对象的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"></bean>

xml注入集合属性

1、注入数组类型属性
2、注入 List 集合类型属性
3、注入 Map 集合类型属性

(1)创建类,定义数组、list、map、set 类型属性,生成对应 set方法

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;
 }
}

(2)在 spring 配置文件进行配置

<!--1 集合类型属性注入-->
<bean id="stu" class="com.atguigu.spring5.collectiontype.Stu">
   <!--数组类型属性注入-->
   <property name="courses">
      <array>
        <value>java 课程</value>
        <value>数据库课程</value>
      </array>
   </property>

 <!--list 类型属性注入-->
   <property name="list">
     <list>
       <value>张三</value>
       <value>小三</value>
     </list>
   </property>
 
<!--map 类型属性注入-->
 <property name="maps">
   <map>
       <entry key="JAVA" value="java"></entry>
       <entry key="PHP" value="php"></entry>
   </map>
   </property>
 
<!--set 类型属性注入-->
   <property name="sets">
     <set>
       <value>MySQL</value>
       <value>Redis</value>
     </set>
   </property>
</bean>

此处的集合只能用在当前的bean

4、在集合里面设置对象类型值

public class Course {
    private String name;
    public void setName(String name) {
        this.name = name;
    }
}

public class Stu {
    private String name;
    //学生选的课程
    private List<Course> coursesLists;
    public void setName(String name) {
        this.name = name;
    }
    public void setCoursesLists(List<Course> courses) {
        this.courses = courses;
    }
}

list集合类型注入对象

<!--创建多个 course 对象-->
<bean id="course1" class="com.atguigu.spring5.collectiontype.Course">
  <property name="cname" value="Spring5 框架"></property>
</bean>
<bean id="course2" class="com.atguigu.spring5.collectiontype.Course">
  <property name="cname" value="MyBatis 框架"></property>
</bean>

<bean id="stu" class="com.atguigu.spring5.collectiontype.Stu">
  <!--注入 list 集合类型,值是对象-->
  <property name="courseList">
    <list>
      <ref bean="course1"></ref>
      <ref bean="course2"></ref>
     </list>
  </property>
</bean>

map集合类型注入对象

<bean id="u1" class="com.itheima.domain.User"/>
<bean id="u2" class="com.itheima.domain.User"/>
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl">
    <property name="userMap">
        <map>
            <entry key="user1" value-ref="u1"/>
            <entry key="user2" value-ref="u2"/>
        </map>
    </property>
</bean>

Properties的注入

<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl">
<property name="properties">
    <props>
        <prop key="p1">aaa</prop>
        <prop key="p2">bbb</prop>
        <prop key="p3">ccc</prop>
    </props>
</property>
</bean>

把集合注入部分提取出来

 有多个bean,可以引入这个公共的list

(1)在spring配置文件中引入名称空间util

(2)使用util 标签完成 list 集合注入提取 

class Book{
    private List<String> list;
    public void setList(List<String> list){
        this.list = list;
    }
}
<!--1 提取 list 集合类型属性注入-->
<util:list id="bookList">
   <value>易筋经</value>
   <value>九阴真经</value>
   <value>九阳神功</value>
</util:list>
<!--2 提取 list 集合类型属性注入使用-->
<bean id="book" class="com.atguigu.spring5.collectiontype.Book">
   <property name="list" ref="bookList"></property>
</bean>

引入其他配置文件(分模块开发)

实际开发中,Spring的配置内容非常多,这就导致Spring配置很繁杂且体积很大,所以,可以将部分配置拆解到其他 配置文件中,而在Spring主配置文件通过import标签进行加载

<import resource="applicationContext-xxx.xml"/>

总结:

spring的重点配置
spring的重点配置

3.1 基于注解方式的注入

1、什么是注解

Spring是轻代码而重配置的框架,配置比较繁重,影响开发效率,所以注解开发是一种趋势,注解代替xml配置 文件可以简化配置,提高开发效率

Spring原始注解主要是替代<Bean>的配置

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

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

(1)@Component
(2)@Service
(3)@Controller
(4)@Repository

* 上面四个注解功能是一样的,都可以用来创建 bean 实例。我们习惯把不同注解用在不同层中,让开发人员清晰当前组件的角色,实际混用都是可以的。

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

开启组件扫描,扫描有注解的类,有注解则创建对象

在配置文件中引入context名称空间

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

com.atgui包下的所有类都能扫描

创建类,在类上面添加创建对象注解

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

开启组件扫描细节配置

<!--示例 1
 use-default-filters="false"表示不使用默认filter,使用自己配置的filter
 context:include-filter ,设置扫描哪些内容
-->

<context:component-scan base-package="com.atguigu" use-default-filters="false">
  <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>//只扫描Controller的注解
</context:component-scan>

<!--示例 2
 下面配置扫描包所有内容
 context:exclude-filter: 设置哪些内容不进行扫描
-->

<context:component-scan base-package="com.atguigu">
 <context:exclude-filter type="annotation" 
 expression="org.springframework.stereotype.Controller"/> //controller注解不扫描
</context:component-scan>

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

(1)@Autowired:根据属性类型进行自动装配
  示例:在service类中注入dao对象
  第一步 创建service 和 dao 对象(在 service 和 dao 类添加创建对象注解)
  第二步 在 service 注入 dao 对象(在 service 类添加 dao 类型属性,在属性上面使用注解)

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

@Repository
public class UserDaoImpl implements UserDao{
    @Override
    public void add() {
        System.out.println("userdao");
    }
}

 (2)@Qualifier:根据名称进行注入

   这个@Qualifier 注解的使用,和上面@Autowired 一起使用。(根据类型注入,一个接口(同类型)有多个实现类,要通过名称进一步确定)

@Service
public class UserService {
    @Autowired
    @Qualifier(value = "userimpl1")
    private UserDao userDao;
    public void add(){
        System.out.println("service Add....");
        userDao.add();
    }
}

@Repository(value = "userimpl1")
public class UserDaoImpl implements UserDao{
    @Override
    public void add() {
        System.out.println("userdao");
    }
}

(3)@Resource:可以根据类型注入,可以根据名称注入(是javax包中的,spring官方更推荐前两个)

//@Resource //根据类型进行注入
@Resource(name = "userDaoImpl1") //根据名称进行注入,此处参数名是name
private UserDao userDao;

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

@Value(value = "abc")
private String name;//abc注入到name中

5、完全注解开发

使用上面的注解还不能全部替代xml配置文件,还需要使用注解替代的配置如下:
    非自定义的Bean的配置:<bean> 
    加载properties文件的配置:<context:property-placeholder>
    组件扫描的配置:<context:component-scan>
    引入其他文件:<import>

(1)创建配置类,替代 xml 配置文件

分核心配置文件:

@PropertySource("classpath:jdbc.properties")//加载类文件夹下的properties
public class DataSourceConfiguration {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")    
    private String url;
    @Value("${jdbc.username}")    
    private String username;
    @Value("${jdbc.password}")
    private String password;

    @Bean(name="dataSource")//返回值存储到Bean容器中
    public DataSource getDataSource() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass(driver);
        dataSource.setJdbcUrl(url);
        dataSource.setUser(username);
        dataSource.setPassword(password);
        return dataSource;
}

主核心配置文件 

@Configuration //作为配置类,替代 xml 配置文件
@ComponentScan(basePackages = {"com.atguigu"})
@Import({DataSourceConfiguration.class})//导入分配置类
public class SpringConfig {
}

(2)编写测试类

@Test
public void testService2() {
   //加载配置类
   ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
   UserService userService = context.getBean("userService",UserService.class);
   System.out.println(userService);
   userService.add();
}

4. IOC接口(BeanFactory)

    1、IOC思想基于IOC容器完成,IOC容器底层就是对象工厂(读取配置文件,通过反射创建对象)
    2、Spring提供两种IOC容器实现方式:(两个接口)
     (1)BeanFactory:IOC容器的基本实现方式,是Spring内部的使用接口,不提供开发人员进行使用。 加载配置文件时候不会创建对象,获取(使用)对象时才去创建对象
     (2)ApplicationContext:BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员进行使用。代表应用上下文,可以通过其实例获得 Spring 容器中的 Bean 对象。 加载配置文件时就会把配置文件对象进行创建(更优,在服务器启动的时候就建好全部需要的对象)

 ApplicationContext的实现类
1)ClassPathXmlApplicationContext
它是从类的根路径下加载配置文件 推荐使用这种
2)FileSystemXmlApplicationContext
它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。
3)AnnotationConfigApplicationContext
当使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。

getBean()方法使用

public Object getBean(String name) throws BeansException {//字符串参数
    assertBeanFactoryActive();
    return getBeanFactory().getBean(name);
}
public <T> T getBean(Class<T> requiredType) throws BeansException {//字节文件参数
    assertBeanFactoryActive();
    return getBeanFactory().getBean(requiredType);
}

其中,当参数的数据类型是字符串时,表示根据Bean的id从容器中获得Bean实例,返回是Object,需要强转。

当参数的数据类型是Class类型时,表示根据类型从容器中匹配Bean实例,当容器中相同类型Bean有多个时,则此方法会报错。

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService1 = (UserService) 
applicationContext.getBean("userService");
UserService userService2 = applicationContext.getBean(UserService.class);

FactoryBean

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

public class MyBean implements FactoryBean<Course> {//泛型类
 //定义返回 bean
 @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 false;
 }
}
<bean id="myBean" class="com.atguigu.spring5.factorybean.MyBean"></bean>
@Test
public void test3() {
 ApplicationContext context =
 new ClassPathXmlApplicationContext("bean3.xml");
 Course course = context.getBean("myBean", Course.class);
 System.out.println(course);
}

定义类型是mybean,返回类型是course

xml自动装配

基于xml的自动装配实际开发中很少用,基本都用注解解决

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

<!--实现自动装配
 bean 标签属性 autowire,配置自动装配
 autowire 属性常用两个值:
 byName 根据属性名称注入 ,注入值 bean 的 id 值和类属性名称一样
 byType 根据属性类型注入
-->
<bean id="emp" class="com.atguigu.spring5.autowire.Emp" autowire="byName">
 <!--<property name="dept" ref="dept"></property>-->
</bean>
<bean id="dept" class="com.atguigu.spring5.autowire.Dept"></bean>

(2)根据属性类型自动注入

<bean id="emp" class="com.atguigu.spring5.autowire.Emp" autowire="byType">
 <!--<property name="dept" ref="dept"></property>-->
</bean>
<bean id="dept" class="com.atguigu.spring5.autowire.Dept"></bean>
<!--<bean id="dept1" class="com.atguigu.spring5.autowire.Dept"></bean>-->此处由于类型相同(Dept)会报错

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值