Spring框架1——IOC容器

一  初识IOC。

   1.创建一个空项目,导入相关的jar包。在官网下载Spring压缩包,以下与Spring相关的jar包在其libs目录下找到。

    <!--
      commons-logging-1.2.jar 日志
      spring-beans-5.3.9.jar
      spring-context-5.3.9.jar
      spring-core-5.3.9.jar
      spring-expression-5.3.9.jar
    -->

      2.编写一个User类。

public class User {
    public void say(){
        System.out.println("哈哈哈");
    }
}

   3.编写一个xml文件,注册User类。

<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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.wsl.demo.dao.User"/>
</beans>

      4.编写测试类,观察结果。

public class TestDemo {
   @Test
    public void testUser(){
       ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
       User user= context.getBean("user", User.class);
       user.say();//哈哈
      }
}

二  什么是IOC(控制反转)?

  Spring IOC 容器,负责实例化、配置和组装 bean。容器通过读取配置元数据来获取关于要实例化、配置和组装哪些对象的指令。配置元数据以 XML、Java 注释或 Java 代码表示。这三句话很好的概括了开头的案例:

  1. 通过容器获得对象并非传统的new:User user1 = context.getBean("user1", User.class);
  2. 容器读取配置元数据:ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
  3. 案例采用的是xml方式配置元数据。

       Spring框架管理对象创建和生命周期的机制称之为控制反转,使用IOC目的是为了降低耦合度

三  IOC原理。

  1.工厂模式,xml解析,反射。

    

 

   2.IOC思想基于IOC容器完成,IOC容器底层就是对象工厂。Spring的IOC容器实现依靠BeanFactory接口ApplicationContext接口。

       

四  IOC容器——管理Bean。

  操作:1.创建对象 2.注入属性(DI)   方式:1.xml  2.注解

       1. xml方式

  1.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"
       xmlns:p="http://www.springframework.org/schema/p"  <!-- 使用p名称空间时引入-->
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--通过set方法注入属性-->
    <bean id="user1" class="com.wsl.bean.User">
        <property name="name" value="张三"/>
        <property name="age" value="19"/>
    </bean>
    <!--通过构造方法注入属性-->
    <bean id="user2" class="com.wsl.bean.User">
        <constructor-arg name="age" value="19"/>
        <constructor-arg name="name" value="李四"/>
    </bean>
    <!--通过p名称空间注入-->
    <bean id="user3" class="com.wsl.bean.User" p:name="王五" p:age="19"/>
</beans>

   属性注入——外部bean,内部bean,级联赋值

    <!--外部bean-->
    <bean id="stu" class="com.wsl.bean.Student">
    <property name="name" value="肖清芳"/>
    <property name="address" ref="adder"/>
    </bean>
    <bean id="adder" class="com.wsl.bean.Address">
        <constructor-arg name="name" value="邙山"/>
        <constructor-arg name="number" value="2"/>
    </bean>
    <!--内部bean-->
    <bean id="stu1" class="com.wsl.bean.Student">
        <property name="name" value="陆大有"/>
        <property name="address">
            <bean class="com.wsl.bean.Address">
                <property name="name" value="小莲子山"/>
                <property name="number" value="1"/>
            </bean>
        </property>
    </bean>
    <!--级联赋值 第一种方式就是外部bean,这里是第二种方式-->
    <bean id="stu2" class="com.wsl.bean.Student">
        <property name="name" value="沙尔汗"/>
        <property name="address" ref="address1"/>
        <property name="address.name" value="洛阳"/>
    </bean>
    <bean id="address1" class="com.wsl.bean.Address">
           <property name="number" value="1"/>
    </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">
    <!--集合注入 方式一-->
    <bean id="hero1" class="com.wsl.bean.Hero">
        <!--数组-->
        <property name="assistants">
            <array>
                <value>李元芳</value>
                <value>张环</value>
            </array>
        </property>
        <!--List-->
        <property name="enemy">
            <list>
                <value>沙尔汗</value>
                <value>贺鲁</value>
            </list>
        </property>
        <!--Set-->
        <property name="way">
            <set>
                <value>便宜行事</value>
                <value>黜置使大人</value>
            </set>
        </property>
        <!--Map,这里演示key为对象的情况-->
        <property name="map">
            <map>
                <entry key-ref="team1" value="蚍蜉撼树,螳臂当车,不自量力"/>
                <entry key-ref="team2" value="井底之蛙,夜郎自大"/>
            </map>
        </property>
    </bean>
    <bean id="team1" class="com.wsl.bean.Team">
        <property name="name" value="蛇灵"/>
        <property name="rank" value="1000"/>
    </bean>
    <bean id="team2" class="com.wsl.bean.Team">
        <property name="name" value="铁手团"/>
        <property name="rank" value="999"/>
    </bean>
</beans>
<?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"
       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 id="hobby">
        <value></value>
        <value></value>
        <value>打篮球</value>
    </util:list>
    <!-- 集合里面是对象-->
    <util:list id="pets">
        <ref bean="pet1"/>
        <ref bean="pet2"/>
    </util:list>
    <bean id="cxk" class="com.wsl.bean.People">
        <property name="hobby" ref="hobby"/>
        <property name="pets" ref="pets"/>
    </bean>
    <bean id="pet1" class="com.wsl.bean.Pet">
        <property name="name" value="小公鸡"/>
        <property name="info" value="咯咯咯"/>
    </bean>
    <bean id="pet2" class="com.wsl.bean.Pet">
        <property name="name" value="小母鸡"/>
        <property name="info" value="下蛋蛋"/>
    </bean>
</beans>

       1.2 普通Bean与工厂Bean 

           普通Bean:配置文件中定义的bean类型就是返回类型     工厂Bean: 配置文件中定义的bean类型跟返回类型可以不同    上面看到了很多普通bean,下面就只介绍工厂bean了。

public class MyBean implements FactoryBean<Pet> {//1.定义一个类使其实现FactoryBean接口
    @Override
    public Pet getObject() throws Exception {//2.重写getObject()方法设置其返回类型
        Pet pet = new Pet();
        pet.setName("dog");
        pet.setInfo("汪汪汪");
        return pet;
    }
}

    <!--配置bean-->
    <bean id="myBean" class="com.wsl.bean.MyBean"/>

   @Test
   public void testBean(){
      ApplicationContext context = new ClassPathXmlApplicationContext("bean5.xml");
      //配置是MyBean类型,返回类型却是Pet类型
      Pet pet = context.getBean("myBean", Pet.class);
   }

       Bean的作用域

  

    <!--将scope设置成多实例-->
    <bean id="animal" class="com.wsl.bean.Animal" scope="prototype"/>

      Animal animal = context.getBean("animal", Animal.class);
      Animal animal1 = context.getBean("animal", Animal.class);
      System.out.println(animal);
      System.out.println(animal1);

    //得到两个不同的对象
     com.wsl.bean.Animal@738dc9b
     com.wsl.bean.Animal@3c77d488

    <!--默认是单实例-->
    <bean id="cxk" class="com.wsl.bean.People"/>

      People cxk = context.getBean("cxk", People.class);
      People cxk1 = context.getBean("cxk", People.class);
      System.out.println(cxk);
      System.out.println(cxk1);

     //得到两个相同的对象
    com.wsl.bean.People@dc7df28
    com.wsl.bean.People@dc7df28

   1.3 Bean的七大生命周期

//1.编写测试类
public class Car {
    private String type;
    public String getType() {
        return type;
    }
    public Car() {
        System.out.println("1.调用无参构造");
    }
    public void setType(String type) {
        System.out.println("2.为属性设置值");
        this.type = type;
    }
    public void initMethod(){
        System.out.println("4.调用初始化方法!");
    }
    public void destroyMethod(){
        System.out.println("7.调用销毁方法!");
    }
}
//2.编写一个类实现BeanPostProcessor接口
public class ProcessModel implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("3.初始化前调用后置处理器方法");
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("5.初始化后调用后置处理器方法");
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}
//3.配置Bean
    <!--设置初始化和销毁方法-->
    <bean id="car" class="com.wsl.bean.Car" destroy-method="destroyMethod" init-method="initMethod">
        <property name="type" value="公交车"/>
    </bean>
    <bean id="process" class="com.wsl.bean.ProcessModel"/>
//4.编写测试代码
   @Test
   public void testProcess(){
     ClassPathXmlApplicationContext  context = new ClassPathXmlApplicationContext("bean6.xml");
      Car car= context.getBean("car", Car.class);
      System.out.println("6.使用:"+car.getType());
      context.close();
   }
//5.观察结果
1.调用无参构造
2.为属性设置值
3.初始化前调用后置处理器方法
4.调用初始化方法!
5.初始化后调用后置处理器方法
6.使用:公交车
7.调用销毁方法!

        1.4 自动装配

    <!-- 自动装配
   bean标签的autowire属性开启
   byName: 根据属性名称装配  若id与属性名称不一致,注入失败(为null)但不会报错
   byType:  根据属性类型装配  若有多个相同类型的bean直接报错
    -->
    <bean id="master" class="com.wsl.bean.Master" autowire="byName"/>
    <bean id="pet" class="com.wsl.bean.Pet"/>

       1.5 外部属性文件

<?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.将我们要设置的属性值写在一个properties文件中
      如:name="cxk"
      message="唱跳rap"
    -->
    <!--2.引入context名称空间
     xmlns:context="http://www.springframework.org/schema/context"
     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    -->
    <!--3.使用context标签就可以将properties文件引进来了-->
    <context:property-placeholder location="classpath:petset.properties"/>
    <!--使用4.${*}
     如:${name}就将”cxk“设置给了pet的name属性
    -->
    <bean id="pet" class="com.wsl.bean.Pet">
        <property name="name" value="${name}"/>
        <property name="info" value="${message}"/>
     </bean>

      2.注解

       2.1创建对象

    <!--1. 引入spring-aop-5.3.9.jar-->
    <!--四个注解:
    @Component(value = "cxk")
    @Repository
    @Controller
    @Service
    他们作用一样,value值可以省略
    -->
    <!--2.在类上添加注解
    @Component(value = "cxk")
    public class User {
    public void say(){
        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"
       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">
    <!--3.开启注解扫描-->
    <context:component-scan base-package="com.wsl.demo"/>
</beans>
                <!-- 组件扫描细节-->
    <!-- 1.想要扫描多个包可以用逗号隔开,也可以设置成上一级目录-->
    <!-- 2.组件扫描配置 设置use-default-filters="false"
    明白这两个单词意思: include:包括,包含   exclude:将..排除在外,除了..之外
    -->
    <context:component-scan base-package="com.wsl.demo.dao" use-default-filters="false">
        <!-- 这个表示只扫描包下带的@Controller注解-->
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
   
    <context:component-scan base-package="com.wsl.demo.dao" use-default-filters="false">
        <!-- 这个表示扫描包下除了@Controller其他注解-->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

       2.2属性注入

    <!-- 开启注解扫描-->
    <context:component-scan base-package="com.wsl.demo"/>
    <!-- 四个注解:
    @Autowired:   根据类型注入
    @Qualifier    根据名称注入 与Autowired一起使用
    @Resource     既可以根据类型又可以根据名称注入 这个注解是javax下的而并非spring的,所以官方不建议使用此注解
    @Value        普通属性注入
    -->
    <!--用法如下  将Dog对象注入
    @Controller
public class Cat {
    下面三个任选一个即可
    @Autowired 或 @Autowired  @Qualifier(value = "dog1") 或 @Resource(name = "dog1")
    private Dog dog;
}
@Service(value = "dog1") public class Dog { @Value(value = "小白") private String name; }
-->

        2.3 完全注解开发

    <!-- 使用注解时xml只配置了包扫描,因此我们可以尝试用配置类代替xml配置文件-->
    <!-- 1.编写配置类
    @Configuration//成为配置类,代替xml文件
    @ComponentScan(basePackages = {"com.wsl.demo"})//扫描包
    public class SpringConfig {
    }
    -->
    <!--2.编写测试类 因为我们未使用xml文件,因此有些许不同
   @Test
    public void testMethod2(){
        读取配置类
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        Cat cat = context.getBean("cat", Cat.class);
        cat.say();
    }
    -->
posted @ 2022-08-31 21:33  wshuanglin  阅读(48)  评论(0)    收藏  举报