IoC容器装配Bean_基于XML配置方式

实例化Bean的四种方式 (了解)

在这里插入图片描述

实例化Bean的四种方式 (了解)

第一种方式 无参数构造器 (最常用)

第一步:创建Bean1.java

package cn.itcast.spring.bean;
//1。默认构造器(spring在创建bean的时候自动调用无参构造器来实例化,相当于new Bean1())
public class Bean1 {
}

第二步:在spring容器applicationContext.xml中配置
applicationContext.xml

    <!-- 实例化 bean的四种方式 -->
    <!-- 1.默认构造器实例化对象 -->
    <bean id="bean1" class="cn.itcast.spring.bean.Bean1"/>

第三步:创建测试类获取bean对象
SpringTest.java

public class SpringTest {
    @Test
    public void test() {
        //创建spring工厂
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        //1.默认构造器获取bean对象
        Bean1 bean1 = (Bean1) ac.getBean("bean1");
        System.out.println("bean1 = " + bean1);
     }
}

第二种方式: 静态工厂方法

第一步:创建Bean2.java
Bean2.java

package cn.itcast.spring.bean;
//1.静态工厂方法构造:用来在初始化bean2的时候,可以初始化其他的东西
public class Bean2 {
}

第二步:创建Bean2Factory.java类

package cn.itcast.spring.bean;
//静态工厂
public class Bean2Factory {
    //静态方法,用来返回对象的实例
    public static Bean2 getBean2(){
        //在做实例化的时候,可以做其他的事情,即可以在这里写初始化其他对象的代码
        //Connection conn....
        return new Bean2();
    }
}

第三步:Spring的容器applicationContext.xml

<!-- 2.静态工厂获取实例化对象 -->
    <!-- class:直接指定到静态工厂类, factory-method: 指定生产实例的方法, spring容器在实例化工厂类的时候会自动调用该方法并返回实例对象 -->
    <bean id="bean2" class="cn.itcast.spring.bean.Bean2Factory" factory-method="getBean2"/>

第四步:测试类进行测试

@Test
	public void test(){
		//先构建实例化获取spring的容器(工厂、上下文)
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		//2.静态工厂
		Bean2 bean2=(Bean2) applicationContext.getBean("bean2");
		System.out.println(bean2);
	}

第三种方式: 实例工厂方法

第一步:创建Bean3.java

//第三种bean,实例工厂方式创建
public class Bean3 {
}

第二步:创建实例工厂Bean3Factory类

package cn.itcast.spring.bean;
//实例工厂:必须new工厂--》bean
public class Bean3Factory {
    //普通的方法,非静态方法
    public Bean3 getBean3() {
        //初始化实例对象返回
        return new Bean3();
    }
}

第三步:Spring容器的配置:applicationContext.xml

<!-- 3:实例工厂的方式实例化bean -->
    <bean id="bean3Factory" class="cn.itcast.spring.bean.Bean3Factory"/>
    <!-- factory-bean相当于ref:引用一个bean对象 -->
    <bean id="bean3" factory-bean="bean3Factory" factory-method="getBean3"/>

第四步:使用测试代码,进行测试:

@Test
	public void test(){
		//先构建实例化获取spring的容器(工厂、上下文)
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		//3.实例工厂
		Bean3 bean3=(Bean3) applicationContext.getBean("bean3");
		System.out.println(bean3);
	}

第四种方式: FactoryBean方式:

第一步: 创建Bean4:

package cn.itcast.spring.bean;

public class Bean4 {
}

第二步: 创建Bean4Factory:

package cn.itcast.spring.bean;

import org.springframework.beans.factory.FactoryBean;

public class Bean4Factory implements FactoryBean<Bean4> {


    //产生对象
    @Override
    public Bean4 getObject() throws Exception {
        return new Bean4();
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}

第三步: 配置applicationContext.xml:

<!--方式四:FactoryBean-->
    <!--spring在实例化对象的时候回判断是否该对象实现了FactoryBean接口,如果实现了就直接调用getObject()方法,并返回执行结果-->
    <bean id="bean4" class="cn.itcast.spring.bean.Bean4Factory"/>

比较四种方式

第一种:最常用
第二、第三种:一些框架初始化的时候用的多。
第四种:spring底层实现的比较多

SpringTest.java

package cn.itcast.spring;

import cn.itcast.spring.bean.Bean1;
import cn.itcast.spring.bean.Bean2;
import cn.itcast.spring.bean.Bean3;
import cn.itcast.spring.bean.Bean4;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringTest {
    @Test
    public void test() {
        //创建spring工厂
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        //1.默认构造器获取bean对象
        Bean1 bean1 = (Bean1) ac.getBean("bean1");
        System.out.println("bean1 = " + bean1);
        System.out.println("");
        System.out.println("");

        //先构建实例化获取spring的容器(工厂、上下文)
        ApplicationContext ac2 = new ClassPathXmlApplicationContext("applicationContext.xml");
        //2.静态工厂
        Bean2 bean2 = (Bean2) ac2.getBean("bean2");
        System.out.println("bean2 = " + bean2);
        System.out.println("");
        System.out.println("");

        //先构建实例化获取spring的容器(工厂、上下文)
        ApplicationContext ac3 = new ClassPathXmlApplicationContext("applicationContext.xml");
        //3.实例工厂
        Bean3 bean3=(Bean3) ac3.getBean("bean3");
        System.out.println("bean3 = " + bean3);
        System.out.println("");
        System.out.println("");

        //先构建实例化获取spring的容器(工厂、上下文)
        ApplicationContext ac4 = new ClassPathXmlApplicationContext("applicationContext.xml");
        //4.FactoryBean
        Bean4 bean4=(Bean4) ac4.getBean("bean4");
        System.out.println("bean4 = " + bean4);
    }
}

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>spring1</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.6.4</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>
    </dependencies>
</project>

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       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">

    <!-- 该 BeanPostProcessor 将自动起作用,对标注 @Autowired 的 Bean 进行自动注入 -->
    <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>

    <!-- bean: spring工厂创建的一个对象(反射机制)
	id/name:对象的名字,可以用来引用或者获取对象, 一般为类名或接口名称的首字母小写
	class:要创建的对象类型的类字符串,类名全路径
 -->
    <bean id="userDao3" class="cn.itcast.spring.UserDaoImpl"/>

    <bean id="userDao4" class="cn.itcast.spring.UserDaoImpl"/>

    <bean id="userService" class="cn.itcast.spring.UserServiceImpl">
        <!-- 注入对象 -->
        <!-- property 根据类中的setter方法进行属性注入 -->
        <!-- name:setter方法的后缀小写,比如setXxx 对应的name为xxx -->
        <!-- ref:引用哪一个bean(对象),值为bean的id/name -->
        <!--用了Autowired就删掉Property,ref,否则报错-->
        <!-- <property name="userDao4" ref="userDao4" />-->
    </bean>

    <!-- 实例化 bean的四种方式 -->
    <!-- 1.默认构造器实例化对象 -->
    <bean id="bean1" class="cn.itcast.spring.bean.Bean1"/>

    <!-- 2.静态工厂获取实例化对象 -->
    <!-- class:直接指定到静态工厂类, factory-method: 指定生产实例的方法, spring容器在实例化工厂类的时候会自动调用该方法并返回实例对象 -->
    <bean id="bean2" class="cn.itcast.spring.bean.Bean2Factory" factory-method="getBean2"/>

    <!-- 3:实例工厂的方式实例化bean -->
    <bean id="bean3Factory" class="cn.itcast.spring.bean.Bean3Factory"/>
    <!-- factory-bean相当于ref:引用一个bean对象 -->
    <bean id="bean3" factory-bean="bean3Factory" factory-method="getBean3"/>

    <!--方式四:FactoryBean-->
    <!--spring在实例化对象的时候回判断是否该对象实现了FactoryBean接口,如果实现了就直接调用getObject()方法,并返回执行结果-->
    <bean id="bean4" class="cn.itcast.spring.bean.Bean4Factory"/>

    <!--
		bean的作用范围
		scope:配置作用范围的,默认值就是singleton单例
	 -->
    <!-- 单例 -->
    <!-- <bean id="singletonBean" class="cn.itcast.spring.c_xmlscope.SingletonBean" scope="singleton"/> -->
    <bean id="singletonBean" class="cn.itcast.spring.SingletonBean"/>
    <!-- 多例 -->
    <bean id="prototypeBean" class="cn.itcast.spring.PrototypeBean" scope="prototype"/>

    <!-- 生命周期调用的两个方法
	init-method:初始化时(后)调用的,bean中的共有方法即可
	destroy-method:销毁时(前)被调用的。
	-->
    <bean id="lifeCycleBean" class="cn.itcast.spring.LifeCycleBean" init-method="init" destroy-method="destroy"/>


    <!-- 构造器注入属性的值 -->
    <bean id="car" class="cn.itcast.spring.Car">
        <!--constructor-arg:告诉spring容器,要调用有参构造方法了,不再调用默认的构造方法了
        new Car(1,"宝马",99999d)
        参数第一组:定位属性
            * index:根据索引定位属性,0表示第一个位置
            * name:根据属性参数名称定位属性
            * type:根据属性数据类型定位属性
        参数第二组:值
            * value:简单的值,字符串
            * ref:复杂的(由spring容器创建的bean对象)
        -->
        <constructor-arg index="0" value="2"/>
        <!-- <constructor-arg index="0" name="id" value="1"/>-->
        <constructor-arg name="name" value="宝马1代"/>
        <!--        <constructor-arg name="name" >
                    <value>宝马2代</value>
                </constructor-arg>-->
        <constructor-arg type="java.lang.Double" value="99999d"/>
        <constructor-arg type="java.lang.Double" value="666f"/>
    </bean>

    <!-- setter方法属性注入:调用默认构造器,相当于new Person() -->
    <bean id="person" class="cn.itcast.spring.Person">
        <!--
        property:专门进行setter属性注入用的标签 。
            * name:setter方法的属性的名字,例如SetXxx-那么name的属性值为xxx。
            * value:简单的值
            * ref:bean的名字,对象的引用
        -->
        <property name="id" value="1001"/>
        <property name="userName" value="John"/>
        <!-- <property name="car" ref="car"/> --><!--等同于-->
        <property name="car">
            <ref bean="car"/>
        </property>
    </bean>
    <bean id="person2" class="cn.itcast.spring.Person" p:id="1002" p:userName="关羽" p:car-ref="car"/>
    <!-- spEL的使用 -->
    <!-- #{person.id} 相当于调用了person的getId()方法 -->
    <bean id="person3" class="cn.itcast.spring.Person"
          p:id="#{1+5}" p:userName="#{'Jack'.toUpperCase()}" p:car="#{car}"></bean>


    <!-- 开启spring的注解功能 :让注解有效了,识别注解-->
    <context:annotation-config/>

    <!-- 配置注解扫描
                context:component-scan:专门扫描含有@Component注解的类,自动将其作为bean
                base-package:要扫描包的路径,包含子包,cn.itcast.spring表示子包下的所有类定义注解都有效
                注解扫描配置的时候,会自动开启注解功能
        -->
    <context:component-scan base-package="cn.itcast.spring"/>

    <!--    <bean id="customerDao" class="cn.itcast.spring.CustomerDao"/>
        <bean id="customerService" class="cn.itcast.spring.CustomerService">
        <property name="customerDao" ref="customerDao"></property>
        </bean>-->

    <!-- xml方式定义bean -->
    <bean id="productDao" class="cn.itcast.spring.ProductDao"/>
    <bean id="productService" class="cn.itcast.spring.ProductService"/>
</beans>

在这里插入图片描述

(4)Spring中Bean的五大作用域及其生命周期 【详解】

Bean的作用域

在这里插入图片描述
项目开发中通常会使用:singleton 单例、 prototype多例
Singleton: 在一个spring容器中,对象只有一个实例。(默认值)
Prototype: 在一个spring容器中,存在多个实例,每次getBean 返回一个新的实例。

第一步:创建类SingletonBean.java和PrototypeBean.java
创建类SingletonBean.java类

package cn.itcast.spring;
//单例bean
public class SingletonBean {
    public SingletonBean() {
        System.out.println("SingletonBean:初始化了单例");
    }
}

创建类PrototypeBean.java类

package cn.itcast.spring;
//多例bean
public class PrototypeBean {
    public PrototypeBean() {
        System.out.println("PrototypeBean初始化了多例的");
    }
}

第二步:定义spring容器,applicationContext.xml:

    <!--
		bean的作用范围
		scope:配置作用范围的,默认值就是singleton单例
	 -->
    <!-- 单例 -->
    <!-- <bean id="singletonBean" class="cn.itcast.spring.c_xmlscope.SingletonBean" scope="singleton"/> -->
    <bean id="singletonBean" class="cn.itcast.spring.SingletonBean"/>
    <!-- 多例 -->
    <bean id="prototypeBean" class="cn.itcast.spring.PrototypeBean" scope="prototype"/>

第三步:测试代码,创建SpringTest.java:

package cn.itcast.spring;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringBeanTest {
    @Test
    public void test() {
        //先构建实例化获取spring的容器(工厂、上下文)
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        //目标1:看看多次获取bean的时候,是不是同一个
        //目标2:看看bean什么时候初始化的
        //获取单例的bean:应该是同一个
        //单例:每次从spring容器中获取的对象,是同一个对象
        //单例初始化:是在spring容器初始化的时候,就初始化了
        SingletonBean singletonBean1 = (SingletonBean) applicationContext.getBean("singletonBean");
        SingletonBean singletonBean2 = (SingletonBean) applicationContext.getBean("singletonBean");
        System.out.println("singletonBean1 = " + singletonBean1);
        System.out.println("singletonBean2 = " + singletonBean2);

        //获取多例的bean:
        //多例:每次从spring容器中获取的对象,不是同一个对象
        //多例初始化:是在getBean的时候初始化,相当于每次getbean就是在new Bean()
        PrototypeBean prototypeBean1 = (PrototypeBean) applicationContext.getBean("prototypeBean");
        PrototypeBean prototypeBean2 = (PrototypeBean) applicationContext.getBean("prototypeBean");
        System.out.println("prototypeBean1 = " + prototypeBean1);
        System.out.println("prototypeBean2 = " + prototypeBean2);

    }
}

在这里插入图片描述
【注意】
单例是默认值,如果需要单例对象,则不需要配置scope。

Bean的生命周期

(4)Spring中Bean的五大作用域及其生命周期 【详解】

通过spring工厂,可以控制bean的生命周期。

在xml配置Bean的初始化和销毁方法

通过 init-method属性 指定实例化后的调用方法
通过 destroy-method属性 指定销毁对象前的方法
在这里插入图片描述
第一步:创建LifeCycleBean,指定一个init的方法,和一个destroy的方法。

package cn.itcast.spring;

public class LifeCycleBean {
    //定义构造方法
    public LifeCycleBean() {
        System.out.println("LifeCycleBean构造器调用了");
    }

    //初始化后自动调用方法:方法名随意,但也不能太随便,一会要配置
    public void init(){
        System.out.println("LifeCycleBean-init初始化时调用");
    }

    //bean销毁时调用的方法
    public void destroy(){
        System.out.println("LifeCycleBean-destroy销毁时调用");
    }

}

第二步:Spring的核心容器,applicationContext.xml的配置

<!-- 生命周期调用的两个方法
	init-method:初始化时(后)调用的,bean中的共有方法即可
	destroy-method:销毁时(前)被调用的。
	-->
    <bean id="lifeCycleBean" class="cn.itcast.spring.LifeCycleBean" init-method="init" destroy-method="destroy" />

第三步:SpringTest.java测试代码:

package cn.itcast.spring;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringBeanLife {

    @Test
    public void test(){
        //先获取spring的容器,工厂,上下文
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        //对于单例此时已经被初始化
        //获取bean
        LifeCycleBean lifeCycleBean=(LifeCycleBean) applicationContext.getBean("lifeCycleBean");
        System.out.println("lifeCycleBean = " + lifeCycleBean);
        //为什么没有销毁方法调用。
        //原因是:使用debug模式jvm直接就关了,spring容器还没有来得及销毁对象。
        //解决:手动关闭销毁spring容器,自动销毁单例的对象
       ((ClassPathXmlApplicationContext) applicationContext).close();
    }
}

测试时查看控制台打印,发现销毁方法没有执行。

提示:销毁方法的执行必须满足两个条件:
1) 单例(singleton)的bean才会可以手动销毁。
2) 必须手动关闭容器(调用close的方法)时,才会执行手动销毁的方法。

在这里插入图片描述
applicationContext.xml

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

    <!-- 该 BeanPostProcessor 将自动起作用,对标注 @Autowired 的 Bean 进行自动注入 -->
    <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>

    <!-- bean: spring工厂创建的一个对象(反射机制)
	id/name:对象的名字,可以用来引用或者获取对象, 一般为类名或接口名称的首字母小写
	class:要创建的对象类型的类字符串,类名全路径
 -->
    <bean id="userDao3" class="cn.itcast.spring.UserDaoImpl"/>

    <bean id="userDao4" class="cn.itcast.spring.UserDaoImpl"/>

    <bean id="userService" class="cn.itcast.spring.UserServiceImpl">
        <!-- 注入对象 -->
        <!-- property 根据类中的setter方法进行属性注入 -->
        <!-- name:setter方法的后缀小写,比如setXxx 对应的name为xxx -->
        <!-- ref:引用哪一个bean(对象),值为bean的id/name -->
        <!--用了Autowired就删掉Property,ref,否则报错-->
        <!-- <property name="userDao4" ref="userDao4" />-->
    </bean>

    <!-- 实例化 bean的四种方式 -->
    <!-- 1.默认构造器实例化对象 -->
    <bean id="bean1" class="cn.itcast.spring.bean.Bean1"/>

    <!-- 2.静态工厂获取实例化对象 -->
    <!-- class:直接指定到静态工厂类, factory-method: 指定生产实例的方法, spring容器在实例化工厂类的时候会自动调用该方法并返回实例对象 -->
    <bean id = "bean2" class="cn.itcast.spring.bean.Bean2Factory" factory-method="getBean2"/>

    <!-- 3:实例工厂的方式实例化bean -->
    <bean id="bean3Factory" class="cn.itcast.spring.bean.Bean3Factory"/>
    <!-- factory-bean相当于ref:引用一个bean对象 -->
    <bean id="bean3" factory-bean="bean3Factory" factory-method="getBean3"/>

    <!--方式四:FactoryBean-->
    <!--spring在实例化对象的时候回判断是否该对象实现了FactoryBean接口,如果实现了就直接调用getObject()方法,并返回执行结果-->
    <bean id="bean4" class="cn.itcast.spring.bean.Bean4Factory"/>

    <!--
		bean的作用范围
		scope:配置作用范围的,默认值就是singleton单例
	 -->
    <!-- 单例 -->
    <!-- <bean id="singletonBean" class="cn.itcast.spring.c_xmlscope.SingletonBean" scope="singleton"/> -->
    <bean id="singletonBean" class="cn.itcast.spring.SingletonBean"/>
    <!-- 多例 -->
    <bean id="prototypeBean" class="cn.itcast.spring.PrototypeBean" scope="prototype"/>
</beans>

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>spring1</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.6.4</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

Bean属性的依赖注入

Spring中bean的注入方式

属性依赖注入的两种方式

什么是Bean属性的注入?就是对一个对象的属性赋值。有两种方式:

  • 第一种:构造器参数注入 new Book(“金瓶梅”,15.8)
  • 第二种:setter方法属性注入(setter方法的规范需要符合JavaBean规范)
    依赖注入(Dependency Injection):它是 Spring 框架核心 IOC 的具体实现。

在编写程序时,通过控制反转,把对象的创建交给了 Spring,但是代码中不可能出现没有依赖的情况。

IOC 解耦只是降低他们的依赖关系,但不会消除。例如:业务层仍会调用持久层的方法。

那这种业务层和持久层的依赖关系,在使用 Spring 之后,就让 Spring 来维护了。

简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取

在这里插入图片描述

构造器参数注入 constructor-arg

第一步:构造器参数注入属性值。
创建Car类,定义构造方法

package cn.itcast.spring;

public class Car {
    private Integer id;
    private String name;
    private Double price;
    private Double test;

    //有参构造
    public Car(Integer id, String name, Double price, Double test) {
        this.id = id;
        this.name = name;
        this.price = price;
        this.test = test;
    }

    @Override
    public String toString() {
        return "Car{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", price=" + price +
                ", test=" + test +
                '}';
    }
}

第二步:配置applicationContext.xml

  <!-- 构造器注入属性的值 -->
    <bean id="car" class="cn.itcast.spring.Car">
        <!--constructor-arg:告诉spring容器,要调用有参构造方法了,不再调用默认的构造方法了
        new Car(1,"宝马",99999d)
        参数第一组:定位属性
            * index:根据索引定位属性,0表示第一个位置
            * name:根据属性参数名称定位属性
            * type:根据属性数据类型定位属性
        参数第二组:值
            * value:简单的值,字符串
            * ref:复杂的(由spring容器创建的bean对象)
        -->
        <constructor-arg index="0" value="2"/>
        <!-- <constructor-arg index="0" name="id" value="1"/>-->
        <constructor-arg name="name" value="宝马1代"/>
        <!--        <constructor-arg name="name" >
                    <value>宝马2代</value>
                </constructor-arg>-->
        <constructor-arg type="java.lang.Double" value="99999d"/>
        <constructor-arg type="java.lang.Double" value="666d"/>
    </bean>

第三步:使用SpringTest.java测试:

package cn.itcast.spring;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringTest1 {
    @Test
    public void test() {
        //spring容器
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取car
        Car car = (Car) applicationContext.getBean("car");
        System.out.println("car = " + car);
    }
 }

在这里插入图片描述

【补充】
1.定位属性的标签,可以混用

<constructor-arg index="0" name="id" value="1"/>

2.自标签的属性赋值问题,可以使用子标签的value,效果和value属性一样

<constructor-arg name="name" value="宝马1代"/>

等同于

<constructor-arg name="name" >
	<value>宝马2代</value>
</constructor-arg>

setter方法属性注入 property

使用的默认的构造器(new Bean()),但必须提供属性的setter方法,使用setter方法也是企业经常使用的属性注入方式
两步:在类中加入setter方法,在配置文件中使用property

第一步:创建Person.java,定义id、name、car属性

package cn.itcast.spring;
/**
 * 定义人类
 * setter方法属性注入
 * 相当于new Person();
 */

public class Person {
    private Integer id;
    private String userName;
    private Car car;

    //必须提供setter属性方法
    public void setId(Integer id) {
        this.id = id;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public void setCar(Car car) {
        this.car = car;
    }

    public Integer getId() {
        return id;
    }
    public String getUserName() {
        return userName;
    }
    public Car getCar() {
        return car;
    }

    @Override
    public String toString() {
        return "Person [id=" + id + ", name=" + userName + ", car=" + car + "]";
    }
}

第二步:配置spring容器applicationContext.xml

<!-- setter方法属性注入:调用默认构造器,相当于new Person() -->
    <bean id="person" class="cn.itcast.spring.Person">
        <!--
        property:专门进行setter属性注入用的标签 。
            * name:setter方法的属性的名字,例如SetXxx-那么name的属性值为xxx。
            * value:简单的值
            * ref:bean的名字,对象的引用
        -->
        <property name="id" value="1001"/>
        <property name="userName" value="John"/>
        <!-- <property name="car" ref="car"/> --><!--等同于-->
        <property name="car">
            <ref bean="car"/>
        </property>
    </bean>

第三步:使用SpringTest.java测试:

    @Test
    public void test1(){
        //spring容器
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取人
        Person person=(Person)applicationContext.getBean("person");
        System.out.println(person);
    }

在这里插入图片描述
【扩展】
1.标签的用法:

<!-- <property name="car" ref="car"/> -->
        <!--等同于-->
		<property name="car">
			<ref bean="car"/>
		</property>

p名称空间的使用和了解

什么是名称空间?
作用:Schema区分同名元素。(有点类似于java的包)
在这里插入图片描述
回顾:Xmlns没有前缀是默认的名称空间。
为简化XML文件的配置,Spring2.5版本开始引入了一个新的p名称空间。简单的说,它的作用是为了简化setter方法属性依赖注入配置的,它不是真正的名称空间

它的使用方法:

p:<属性名>="xxx" 引入常量值
p:<属性名>_ref="xxx" 引用其它Bean对象

操作步骤:
第一步:引入p名称空间
applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"

	   xmlns:p="http://www.springframework.org/schema/p"
	   
       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">

第二步:将 子元素 简化为 元素的属性注入

 <!-- 使用p名称空间简化setter方法属性注入 -->
    <!--
    p:name:简单数据类型的属性注入
    P:car-ref:复杂数据类型(bean)的属性注入
    -->
    <bean id="person2" class="cn.itcast.spring.Person" p:id="1002" p:userName="关羽" p:car-ref="car"/>

第三步:测试

    @Test
    public void test2(){
        //spring容器
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        Person person2=(Person)applicationContext.getBean("person2");
        System.out.println(person2);
    }

配置时不需要 子元素,简化了配置 .

在这里插入图片描述

spEL表达式的使用(会用即可)

spEL(Spring Expression Language)是一种表达式语言,它是spring3.x版本的新特性。
它的作用是:支持在运行时操作和查询对象,其语法类似统一的EL语言,但是SpEL提供了额外的功能,功能更强大。

什么是EL、OGNL、spEL?

EL:操作servlet相关的一些对象和相关的值
OGNL:主要操作struts2值栈,mybatis的动态sql
spEL:操作bean相关的

语法: #{…} , 引用另一个Bean 、属性、 方法 , 运算
SpEL表达式的使用功能比较多,Bean操作相关的通常有:

  • #{beanid} 引用Bean(具体对象)
  • #{beanId.属性} 引用Bean的属性
  • #{beanId.方法(参数)} 调用Bean的方法

案例一:配置applicationContext.xml

    <!-- spEL的使用 -->
    <!-- #{person.id} 相当于调用了person的getId()方法 -->
    <bean id="person3" class="cn.itcast.spring.Person"
          p:id="#{1+5}" p:userName="#{'Jack'.toUpperCase()}" p:car="#{car}"></bean>
    @Test
    public void test3(){
        //spring容器
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        Person person2=(Person)applicationContext.getBean("person3");
        System.out.println(person2);
    }

在这里插入图片描述

如果抛出异常:
在这里插入图片描述
需要在Person对象中调用get方法,获取属性值,然后赋值到Person对象name的属性中。

public Integer getId() {
		return id;
	}
	public String getName() {
		return name;
	}
	public Car getCar() {
		return car;
	}
	@Override
	public String toString() {
		return "Person [id=" + id + ", name=" + name + ", car=" + car + "]";
    <!-- spEL表达式 -->
    <!-- car.id相当于car.getId() -->
    <bean id="person4" class="cn.itcast.spring.Person" p:id="#{1+1}" p:userName="#{'Tom'.toUpperCase()}" p:car="#{car}"/>
    @Test
    public void test4(){
        //spring容器
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        Person person2=(Person)applicationContext.getBean("person4");
        System.out.println(person2);
    }

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值