Spring IOC

1. Spring特点:

  • 方便解耦,简化开发
  • AOP编程的支持
  • 方便程序的测试
  • 方便和其他框架进行整合
  • 降低JavaEE API的使用难度

2. 入门案例:

  • IntelliJ里file -> project structure -> Module -> + icon -> add spring
  • 创建Spring 配置文件:
    • 该文件是一个XML文件,并且作为粘合bean的粘合剂类。
    • 这个文件需要在src目录下创建。

XML文件配置User class实体:

<?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">

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

User实体类:

package com.atguigu.spring5;

public class User {
    public void add() {
        System.out.println("successful!");
    }
}

测试类去检查User实体类是否在配置文件里创建:

 @Test
 public void testAdd(){
   //加载spring配置文件
 	ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
 	User user = context.getBean("user", User.class);
 	System.out.println(user);
 	user.add();
 }

output:

com.atguigu.spring5.User@4fb3ee4e
successful!
  • ClassPathXmlApplicationContext() 是用来加载beans的配置文件并最终基于所提供的API,它处理创建并初始化所有的对象,即在配置文件中提到的beans。
  • 第二步是使用一创建的上下文的getBean()方法来获得所需的bean。这个方法使用bean的id返回一个最终可以转换为实际对象的通用对象。一旦有了对象,你就可以使用这个对象点用任何类的方法。
  • bean.xml 用于给不同的bean分配唯一的id,并且控制不同值的对象的创建,而不会影响Spring的任何源文件

3. IOC容器原理:

  • 什么是IOC:

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

    • XML解析,工厂模式,反射
    • IOC 过程:
      • xml配置文件, 配置创建对象 ex: <bean id="dao" class="com.atguigu.UserDao"></bean>
      • 有service类和dao类,创建工厂类近一步降低耦合度
    class UserFactory {
    	public static UserDao getDao(){
    		String classValue = class属性值;	//xml解析
    		Class class = Class.forName(classValue); //2.通过反射创建对象
    		return (UserDao)class.newInstance();
    	}
    }
    
  • IOC接口:

    • IOC思想基于IOC容器完成,IOC容器底层就是对象工厂:
    • Spring提供IOC容器实现两种方式:(两个接口)
      • BeanFactory: IOC容器基本实现,是Spring里内部的使用接口, 不提供开发人员使用。(加载配置文件的时候不会创建对象,在获取对象(使用)才去创建对象)

      • ApplicationContext: BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员使用。(加载配置文件的时候就可以创建对象)

4. IOC操作Bean管理:

  • Bean管理指的两个操作
  • Spring创建对象
  • Spring注入属性
  • IOC操作Bean管理(基于XML):

    • 基于xml方式创建对象:

      example:
        <bean id="user" class="com.atguigu.spring5.User"></bean>
      
      • 在spring配置文件中使用bean标签,标签里面添加对应属性,就可以实现对象创建
      • 在bean变迁有很多属性,介绍常用属性:
        • id属性:相当于html tag里的id,他是唯一的标识
        • class属性: 类的全路径(包和类的路径)
      • 在创建对象的时候,默认也是执行无参数的构造方法完成对象创建
    • 基于xml方式注入属性:

      • DI (Dependency Injection): 依赖注入,就是注入属性:

        • 第一种无参数的构造注入

          <!--set方法注入属性-->
          <bean id="book" class="com.atguigu.spring5.Book">
          <property name="bname" value="yijingjing"></property>
          <property name="bauthor" value="damo"></property>
          </bean>
          
        • 第二种是有参数的构造进行注入

          <!--用有参构造注入属性-->
          <bean id="orders" class="com.atguigu.spring5.Orders">
          <constructor-arg name="orderName" value="电脑"></constructor-arg>
          <constructor-arg name="address" value="China"></constructor-arg>
          </bean>
          
      • IOC操作Bean管理(xml注入其他类型属性):

        • 字面量

          • null值:
          <property name="address">
          	<null></null>
          </property>
          
          • 属性值包含特殊符号:
          <!--属性值中包含特殊符号 *把带特殊符号内容写到CDATA-->
          <property name="address">
          	<value><![CDATA[<<南京>>]]></value>
          </property> 
          
      • 注入属性-外部bean

        • 创建两个类service类和dao类
        • 在service调用dao里面的方法
        • 在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..............");
                userDao.update();
            }
        }
        

    xml配置文件:

    <!--service和dao对象创建-->
    <bean id="userService" class="com.atguigu.spring5.service.UserService">
    		<!--注入userDao对象: 类里面的属性名称-->
        	<property name="userDao" ref="userDaoImpl"></property>
    </bean>
    <bean id="userDaoImpl" class="com.atguigu.spring5.dao.UserDaoImpl"></bean>
    
  • 注入属性-内部bean和级联赋值:
    * 一对多关系:部门和员工
    * 在实体类之间表示一对多关系
    * 在Spring配置文件中配置

<!--内部bean-->
<bean id="emp" class="com.atguigu.spring5.bean.Emp">
		<!--先设置两个普通的属性-->
		<property name= "gender" value=""></property>
    	<property name= "name" value="lucy"></property>
		<property name="dept">
    		<bean id="dept" class="com.atguigu.spring5.bean.Dept">
        		<property name="dname" value="安保部"></property>
    		</bean>
		</property>
</bean>
  • 注入属性-级联赋值:

    <bean id="emp" class="com.atguigu.spring5.bean.Emp">
    	<!--先设置两个普通的属性-->
    	<property name= "gender" value=""></property>
    	<property name= "name" value="lucy"></property>
    	<property name="dept" ref="dept">
    	</property>
    </bean>
    <bean id="dept" class="com.atguigu.spring5.bean.Dept">
    	<property name="dname" value="安保部"></property>
    </bean>
    
  • IOC操作Bean管理(XML注入集合属性):

    • 注入数组类型属性

    • 注入List集合类型属性

    • 注入Map集合类型属性

    • 注入Set集合类型属性

    • 注入对象class类型属性:

      <!--集合类型属性注入-->
      <bean id="student" class="com.atguigu.spring5.collectiontype.Student">
          <!--注入数组类型属性-->
          <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>
           <!--注入对象class类型属性·-->
      	 <property name="courseList">
          	<list>
            		<ref bean=""></ref>
          	</list>
      	</property>
      </bean>
      
  • 在集合里面设置对象类型值

        <!--创建多个对象-->
        <bean id="course1" class="com.atguigu.spring5.collectiontype.Courses">
            <property name="c_name" value="Spring5框架">
    
            </property>
        </bean>
        <bean id="course2" class="com.atguigu.spring5.collectiontype.Courses">
            <property name="c_name" value="MyBatis框架">
    
            </property>
        </bean>
    
  • 把集合注入部分提取出来:

    • 在Spring配置文件中引入名称空间util

      <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"
      	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">
      
    • 使用util标签完成list集合注入

      <!--1.提取list集合类型属性注入-->
      <util:list id="bookList">
          <value>book1</value>
          <value>book2</value>
          <value>book3</value>
      </util:list>
      <!--2.提取list集合类型属性注入使用-->
      <bean id="book" class="com.atguigu.spring5.collectiontype.Book">
          <property name="list" ref="bookList"></property>
      </bean>
      
  • IOC操作Bean管理(FactoryBean):

    • Spring有两种类型bean,一种普通bean,另外一种工厂bean(FactoryBean)

    • 普通bean:在配置文件中定义bean类型就是返回类型

    • 工厂bean:在配置文件定义bean类型可以和返回类型不一样

      • 第一步创建类,让这个类作为工厂bean,实现接口FactoryBean:
      public class MyBean implements FactoryBean<Courses> {
          //定义返回bean
          @Override
          public Courses getObject() throws Exception {
              Courses course = new Courses();
              course.setC_name("abc");
              return course;
          }
          @Override
          public Class<?> getObjectType() {
              return null;
          }
          @Override
          public boolean isSingleton() {
              return FactoryBean.super.isSingleton();
          }
      }
      
      • 第二步实现接口里面的方法,在实现的方法中返回的bean类型
       	@Test
      	public void test3(){
      		ApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
      		Courses bean = context.getBean("myBean", Courses.class);
      		System.out.println(bean);
      	}
      

      output:

      Courses{c_name='abc'}
      
  • IOC操作Bean管理(bean作用域):

    • 在Spring里面,设置创建bean实例是单实例还是多实例 (检查单实例和多实例对象看多个对象的地址是否相同)
    • 在Spring里面,默认情况下,bean是单实例对象
    • 如何设置单实例还是多实例
      • 在Spring配置文件bean标签里面有属性(scope)用于设置单实例还是多实例
      • singleton:表示单实例对象
      • prototype:表示多实例对象

    prototype example:
    XML文件:

        <bean id="book" class="com.atguigu.spring5.collectiontype.Book" scope="prototype">
        	<property name="list" ref="bookList"></property>
    	</bean>
    

    测试文件:

    ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
    Book book1 = context.getBean("book", Book.class);
    Book book2 = context.getBean("book", Book.class);
    System.out.println(book1);
    System.out.println(book2);
    

    output:

    com.atguigu.spring5.collectiontype.Book@5c80cf32
    com.atguigu.spring5.collectiontype.Book@7d900ecf
    
  • IOC操作Bean管理(bean生命周期):

    • 生命周期:

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

      • 通过构造器创建bean实例(无参数构造)
      • 为bean的属性来设置值和对其他bean的引用(调用set方法)
      • 把bean实例传递给bean后置处理器的方法(postProcessBeforeInitialization)
      • 调用bean的初始化的方法(需要进行配置初始化方法)
      • 把bean实例传递给bean后置处理器的方法(postProcessAfterInitialization)
      • bean可以使用了(对象获取到了)
      • 当容器关闭的时候,调用bean销毁的方法(需要进行配置销毁的方法)
    • 后置处理器的设置会适用当前配置文件所有的bean对象

    • 添加后置处理器: 创建类,实现接口BeanPostProcessor, 创建后置处理器

    • 演示bean生命周期:

      后置处理器文件:

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

测试文件:

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
beanlife life = context.getBean("lifecycle", beanlife.class);
System.out.println("第四步 获取对象");
	
//手动让bean实例销毁
context.close();

XML文件:

		<bean id="lifecycle" class="com.atguigu.spring5.lifecycle.beanlife" init-method="initMethod" destroy-method="destroyMethod">
                <property name="o_name" value="手机"></property>
        </bean>
         <!--配置后置处理器-->
        <bean id="myBeanPost" class="com.atguigu.spring5.bean.MyBeanPost"></bean>
  • IOC操作Bean管理(XML自动装配):

    • 什么是自动装配:

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

      • bean标签属性autowire,配置自动路径
      • autowire 属性常用两个值:
        • byName: 根据属性名称注入,注入值bean的id值和类的属性名称一样
        • byType:根据属性类型注入
      <bean id="emp" class="com.atguigu.spring5.autowire.Emp" autowire="byName">
      </bean>
      <bean id="dept" class="com.atguigu.spring5.autowire.Dept"></bean>
      
  • IOC操作Bean管理(外部属性文件):

    • 直接配置数据库的信息
      • 配置druid连接池
      • 引入druid连接池的jar包
    • 通过引用外部的属性文件配置数据库连接池:
      • 创建外部属性文件(example: properties格式文件,写数据库信息)
prop.driverClass=com.mysql.jdbc.Driver
prop.url=jdbc:mysql://localhost:3306/campus_jobs
prop.userName=root
prop.password=root
  • 把外部properties属性文件引入到spring配置文件中
    • 引入context名称空间
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">
  • 在Spring配置文件中使用标签引入外部属性文件
		<!--引入外部属性文件-->
    	<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
		<!-- DruidDataSource dataSource = new DruidDataSource();-->
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
	            <!--dataSource.setDriverClassName("com.mysql.jdbc.Driver"); set方法注入-->
	            <!-- 获取properties文件内容,根据key获取,使用Spring表达式获取 -->
	            <property name="driverClassName" value="${prop.driverClass}"></property>
	            <property name="url" value="${prop.url}"></property>
	            <property name="username" value="${prop.userName}"></property>
	            <property name="password" value="${prop.password}"></property>
        </bean>
  • IOC操作Bean管理(基于注解方式):
    • 什么是注解:

      • 注解是代码特殊标记, 格式:@注解名称(属性名称=属性值,属性名称=属性值…)
      • 使用注解,注解作用在类的上面,方法上面,属性上面
      • 使用注解的目的:简化XML配置
    • Spring 针对 bean 管理中创建对象提供注解:

      • @Component
      • @Service
      • @Controller
      • @Repository
    • 上面四个注解功能是一样的,都可以用来创建bean实例

    • 基于注解方式实现对象创建:

      • 开启组件扫描(XML文件):
      <!--开启组件扫描
       1.如果扫描多个包,多个包使用逗号隔开
       2.扫描包上层目录
      -->
      <context:component-scan base-package="com.atguigu.spring5"></context:component-scan>
      
      • 创建类, 在类上面添加创建对象注解:
      //value属性值可以不写,默认值为类名称,首字母小写
      @Component(value="userService") //<bean id="userService" class="..."
      public class UserService {
          //创建UserDao类型属性,生成set方法
          public void add(){
              System.out.println("service add..............");
          }
      }
      
    • 开启组件扫描细节配置:

      <!--示例1
      use-default-filters="false" 表示现在不使用默认filter,自己配置filter
      context:include-filter: 设置扫描哪些内容 annotation and Controller 表示只扫描包里Controller的类
       -->
       <context:component-scan base-package="com.atguigu.spring5" use-default-filters="false">
      	 <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
       </context:component-scan>
      <!--示例2
      下面配置扫描包所有内容
      context:exclude-filter: 设置不去扫描哪些class
       -->
      <context:component-scan base-package="com.atguigu.spring5">
      	 <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
      </context:component-scan>
      
    • 基于注解方式实现属性注入

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

      • @Qualifer:根据属性名称进行注入

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

      • @Value: 注入普通类型属性 (相当于property)

      • 第一步 把service和dao对象创建, 在service和dao类添加创建对象注解

      • 第二步 在 service注入dao对象,在service类添加dao类型属性,在属性上面使用注解

        @Autowired //定义Dao类型,不需要添加set方法 添加注入属性注解 //根据类型进行注入
        private UserDao userDao;
        
    • 纯注解开发:

      • 创建配置类,替代XML文件:
      @Configuration
      @ComponentScan(basePackages={"com.atguigu"})
      public class SpringConfig {
      		
      }
      
      • 编写测试类
       ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值