零基础学JavaWeb开发(十九)之 spring框架(2)

29 篇文章 2 订阅

3.3、SpringBean的注入方式

3.3.1、创建对象和set方法注入属性

1. 什么是Bean管理

使用spring创建对象

使用spring注入属性

2. Bean的管理有两种方式

1. 基于XML方式配置

基于XML方式创建对象

<bean id="userEntity" class="com.mayikt.entity.UserEntity"></bean>

在spring的配置文件中,会配置一个bean标签,注入bean的信息 创建bean对象

Id:获取bean对象 唯一bean对象的名称; bean的名称不允许重复

Class属性: 类的完整路径地址(类名称+包名称)

默认底层使用反射技术执行无参数构造函数

2. 基于xml方式注入属性

DI 依赖注入: 对象的属性注入值; (spring实现)

1. 第一种实现方式:基于对象属性set方法实现

<bean id="bookEntity" class="com.mayikt.entity.BookEntity">
    <property name="bookName" value="蚂蚁课堂面试宝典"></property>
    <property name="bookPrice" value="108.00"></property>
</bean>
在Bean标签下 在定义一个属性<property>标签
Name:类中的属性名称 
Value:需要注入属性值

3.3.2、有参构造函数注入属性

实例类

public class OrderEntity {
    private String orderId;
    private String orderName;

    public OrderEntity(String orderId, String orderName) {
        this.orderId = orderId;
        this.orderName = orderName;
    }

    @Override
    public String toString() {
        return "OrderEntity{" +
                "orderId='" + orderId + '\'' +
                ", orderName='" + orderName + '\'' +
                '}';
    }
}

Xml配置文件

<bean id="orderEntity" class="com.mayikt.entity.OrderEntity">
 <!--
        <constructor-arg name="orderId" value="123456"></constructor-arg>
    <constructor-arg name="orderName" value="来龙虎山学习啦"></constructor-arg>
  -->
    <constructor-arg index="0" value="123456"></constructor-arg>
    <constructor-arg index="1" value="来龙虎山学习啦"></constructor-arg>
</bean>

<constructor-arg name 指定参数列表名称

<constructor-arg index 指定参数列表索引

3.3.3、p名称空间注入

1. Xml头部引入P标签

<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"></bean>

2. 使用p标签注入属性:

<bean id="bookEntity" class="com.mayikt.entity.BookEntity" p:bookName="mayikt" p:bookPrice="66">
</bean>

使用p标签为属性注入值:调用set方法注入值

3.3.4、注入空值和特殊符号

注入空值属性

<bean id="bookEntity2" class="com.mayikt.entity.BookEntity">
    <property name="bookName" value="mayikt">
    </property>
    <property name="bookPrice" >
        <null></null>
    </property>

注入特殊符号

转移注入方式

<< 转移为:<<

>>转移为:>>

<bean id="bookEntity3" class="com.mayikt.entity.BookEntity">
    <!--    <property name="bookName" value="<<武汉>>"></property> -->
    <property name="bookName" value="<<武汉>>"></property>
    <property name="bookPrice">
        <null></null>
    </property>
</bean>

Cdata注入方式

<![CDATA[<<>>]]>

<bean id="bookEntity4" class="com.mayikt.entity.BookEntity">
    <!--    <property name="bookName" value="<<武汉>>"></property> -->
    <property name="bookName">
        <value><![CDATA[<<武汉>>]]></value>
    </property>
    <property name="bookPrice">
        <null></null>
    </property>
</bean>

3.3.5、注入属性外部bean

Com.mayikt.controller---控制层

Com.mayikt.service----业务逻辑层

MemberService ##new MemberDao().

Com.mayikt.dao----数据库访问层

MemberDao----

Com.mayikt.service

调用:memberService

Com.mayikt.dao

MemberDaoImpl

public interface MemberDao {
    void addMember();
}
public class MemberDaoImpl implements  MemberDao {
   public void addMember() {
       System.out.println("dao member");
    }
}
import com.mayikt.dao.MemberDao;
import com.mayikt.dao.MemberDaoImpl;

public class MemberService {
    private MemberDao memberDao;

    public MemberDao getMemberDao() {
        return memberDao;
    }

    public void setMemberDao(MemberDao memberDao) {
        this.memberDao = memberDao;
    }

    public void addMember() {
        System.out.println("<<<Service Service>>");
        // 原始的方式
//        MemberDao memberDao = new MemberDaoImpl();
//        memberDao.addMember();
        memberDao.addMember();
    }
}
<?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">


    <!--
     注入useService
     -->
    <bean id="memberService" class="com.mayikt.service.MemberService">
        <!--  注入userDao
         name 属性值: 类中属性的名称;
         ref 创建MemberDaoImpl类的 bean的id
         -->
        <property name="memberDao" ref="memberDao"></property>
    </bean>
    <bean id="memberDao" class="com.mayikt.dao.MemberDaoImpl"></bean>
</beans>

3.3.6、注入内部bean

1. 数据库表一对多或者一对一的关系

2. 部门--n多个员工 一对多

3. 站在员工角度考虑员工属于那个部门

4. 站在部门的角度考虑部门下n多个员工

1. 在数据库中表中有一对一一对多的关系;

2. 一对多关系;部门与员工 一个部门会有多个员工 一个员工属于一个部门;

3. 实体类之间表示一对多的关系;

实体类员工对象

public class EmpEntity {

    private String name;
    private Integer age;
    /**
     * 员工属于那个部门
     */
    private  DeptEntity deptEntity;
    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public void setDeptEntity(DeptEntity deptEntity) {
        this.deptEntity = deptEntity;
    }

    @Override
    public String toString() {
        return "EmpEntity{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", deptEntity=" + deptEntity +
                '}';
    }
}

部门对象

public class DeptEntity {
    private String name;
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "DeptEntity{" +
                "name='" + name + '\'' +
                '}';
    }
}

Xml相关配置

<!--内部bean -->
<bean id="empEntity" class="com.mayikt.entity.EmpEntity">
    <!--设置属性name/age -->
    <property name="name" value="mayikt"></property>
    <property name="age" value="21"></property>
    <!-- 嵌入部门bean-->
    <property name="deptEntity">
        <bean id="deptEntity" class="com.mayikt.entity.DeptEntity">
            <property name="name" value="教育部门"></property>
        </bean>
    </property>

</bean>

3.3.7、注入级联赋值

写法1

<bean id="empEntity" class="com.mayikt.entity.EmpEntity">
    <!--两个属性-->
    <property name="name" value="mayikt"></property>
    <property name="addres" value="湖北省武汉市"></property>
    <!--级联赋值-->
    <property name="deptEntity" ref="deptEntity"></property>
</bean>
<bean id="deptEntity" class="com.mayikt.entity.DeptEntity">
    <property name="name" value="教育部门"></property>
</bean>

写法2

<bean id="empEntity" class="com.mayikt.entity.EmpEntity">
    <!--两个属性-->
    <property name="name" value="mayikt"></property>
    <property name="addres" value="湖北省武汉市"></property>
    <!--级联赋值-->
    <property name="deptEntity" ref="deptEntity"></property>
    <property name="deptEntity.name" value="教育部门"></property>
</bean>
<bean id="deptEntity" class="com.mayikt.entity.DeptEntity">
</bean>

注意:需要在员工实体类新增:deptEntity get方法。

3.3.8、注入集合类型属性

1. 注入数组类型

2. 注入list集合类型

3. 注入Map集合类型属性

4. 注入set集合属性

实体类

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class StuEntity {
    //1.数组属性
    private String[] arrays;
    //2.list集合属性
   private List<String> list;
    //3.Map
    private Map<String,String> map;
    //4.Set
    private Set<String> set;

    public void setArrays(String[] arrays) {
        this.arrays = arrays;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public void setMap(Map<String, String> map) {
        this.map = map;
    }

    public void setSet(Set<String> set) {
        this.set = set;
    }

    @Override
    public String toString() {
        return "StuEntity{" +
                "arrays=" + Arrays.toString(arrays) +
                ", list=" + list +
                ", map=" + map +
                ", set=" + set +
                '}';
    }
}

配置文件

<bean id="stuEntity" class="com.mayikt.entity.StuEntity">
    <!--数组类型注入-->
    <property name="arrays">
        <array>
            <value>mayikt01</value>
            <value>mayikt02</value>
        </array>
    </property>
    <!--list-->
    <property name="list">
        <list>
            <value>语文</value>
            <value>数学</value>
        </list>
    </property>
    <!--Map-->
    <property name="map">
       <map>
           <entry key="张三丰" value="23"></entry>
           <entry key="小薇" value="25"></entry>
       </map>
    </property>
    <!--Set-->
    <property name="Set">
       <set>
           <value>01</value>
           <value>02</value>
       </set>
    </property>
</bean>

集合类型为对象

private List<CourseEntity> courses;
public void setCourses(List<CourseEntity> courses) {
    this.courses = courses;
}

public class CourseEntity {
    private String name;

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

    @Override
    public String toString() {
        return "CourseEntity{" +
                "name='" + name + '\'' +
                '}';
    }
}
<?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="stuEntity" class="com.mayikt.entity.StuEntity">
        <!--对我们的list属性赋值-->
        <property name="list">
            <list>
                <value>list01</value>
                <value>list02</value>
            </list>
        </property>
        <!--对我们的arrays属性赋值-->
        <property name="arrays">
            <array>
                <value>mayikt01</value>
                <value>mayikt02</value>
            </array>
        </property>
        <!--对我们的map属性赋值-->
        <property name="map">
            <map>
                <entry key="mayikt" value="张三丰"></entry>
                <entry key="xiaowei" value="小薇"></entry>
            </map>
        </property>
        <!--对我们的set属性赋值-->
        <property name="set">
            <set>
                <value>list01</value>
                <value>list02</value>
            </set>
        </property>
        <property name="courses" >
            <list>
                <ref bean="courseEntity1"></ref>
           

集合注入部分提取公共

1. 需要先引入一个util名称空间

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

2. 使用util标签 注入

<?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="list">
        <value>mayikt01</value>
        <value>mayikt02</value>
    </util:list>
    <bean id="stuEntity" class="com.mayikt.entity.StuEntity">
        <property name="list" ref="list"></property>
    </bean>
</beans>

3.3.9、IOC操作Bean的管理

1. Spring中两种类型bean,一种是为普通的bean,另外一种是工厂bean

FactoryBean

2. 普通Bean:在配置文件中定义什么类型与返回的类型需一致;

3. 工厂Bean:在配置文件中定义Bean类型与返回类型可以不一致;

创建一个类,这个类是为工厂Bean,实现FactoryBean接口

import com.mayikt.entity.UserEntity;
import org.springframework.beans.factory.FactoryBean;

public class MayiktBean implements FactoryBean<UserEntity> {
    /**
     * 定义返回bean
     *
     * @return
     * @throws Exception
     */
    public UserEntity getObject() throws Exception {
        return new UserEntity();
    }

    public Class<?> getObjectType() {
        return null;
    }
}
public static void main(String[] args) {
    ClassPathXmlApplicationContext app =
            new ClassPathXmlApplicationContext("spring_08.xml");
    UserEntity mayiktBean = (UserEntity) app.getBean("mayiktBean");
    System.out.println(mayiktBean);
}

3.4、Spring的工厂Bean

3.4.1、SpringBean的作用域

什么是作用域?

设定bean作用域是为单例还是多例

作用域单例与多例有什么区别呢?

1. 单例的作用域:每次在调用getbean方法获取对象都是为同一个对象;

2. 多例的作用域:每次在调用getbean方法获取对象都是一个

新的对象。

注意:在spring默认的情况下,bean的作用域就是为单例 节约服务器内存。

单例:

在同一个jvm中,该bean对象只会创建一次。

多例:

在同一个jvm中,该bean对象可以被创建多次。

设定对象单例还是多例

在spring的默认的情况下,springbean的作用域为单例。

1.单例就是每次获取bean都是同一个对象;

2.多例就是每次获取bean都是新的一个对象;

单例:在同一个jvm中该bean只能存在一个实例;

多例子:在同一个jvm中该bean存在多个实例;

证明:如果是为单例,则两个对象地址都是一样的,

多例子对象则两个对象地址不一样。

单例配置:

<bean id="userEntity" class="com.mayikt.entity.UserEntity" scope="singleton"></bean>

默认就是为单例子;

多例配置:

<bean id="userEntity" class="com.mayikt.entity.UserEntity" scope="prototype"></bean>

3.4.2、SpringBean的生命周期

简单分为:实例化→属性赋值→初始化→销毁

生命周期概念:

1. 对象的创建与销毁的过程,类似之前学习servlet生命的周期过程。

生命周期的原理:

1. 通过构造函数创建bean对象(默认执行无参构造函数 底层基于反射实现)

2. 为bean的属性设置 (使用反射调用set方法)

3. 调用bean的初始化的方法(需要单独在类中配置初始化的方法)

4. 正常使用bean对象

5. Spring容器关闭,调用该类的销毁回调的方法(需要单独在类中配置销毁的方法)

public class MemberEntity {
    private String name;
    public MemberEntity(){
        System.out.println("[第一步]-无参构造函数被执行---反射机制调用");
    }

    public void setName(String name) {
        System.out.println("[第二步]-set方法初始化属性---反射机制调用");
        this.name = name;
    }

    /**
     * 回调调用init初始化方法
     */
    public void initMethod(){
        System.out.println("[第三步]-回调调用init初始化方法");
    }

    /**
     * destroyMethod
     */
    public void destroyMethod(){
        System.out.println("[第五步]-回调调用destroyMethod方法");
    }
}
<bean id="memberEntity" class="com.mayikt.entity.MemberEntity" init-method="initMethod" destroy-method="destroyMethod">
   <property name="name" value="mayikt"></property>
</bean>
<bean id="mayiktBeanPost" class="com.mayikt.bean.MayiktBeanPost"></bean>
import com.mayikt.entity.MemberEntity;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test07 {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext app =
                new ClassPathXmlApplicationContext("spring_07.xml");
       MemberEntity memberEntity= app.getBean("memberEntity",MemberEntity.class);
        System.out.println("[第四步]-获取使用到的memberEntity");
        System.out.println(memberEntity);
        // 手动让bean容器销毁
        app.close();
    }
}

Bean的后置处理器 作用提供更多的扩展功能 BeanPostProcessor

相关演示代码

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class MayiktBeanPost implements BeanPostProcessor {
    /**
     * 调用初始化方法之前执行
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("在bean 初始化方法之前执行");
        return bean;
    }

    /**
     * 调用初始化方法之后执行
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("在bean 初始化方法之后执行");
        return bean;
    }
}
<bean id="mayiktBeanPost" class="com.mayikt.bean.MayiktBeanPost"></bean>

1.通过构造函数创建bean对象(默认执行无参构造函数 底层基于反射实现)

2.为bean的属性设置 (使用反射调用set方法)

3.将bean传递给后置处理器 调用初始化方法之前执行

4.调用bean的初始化的方法(需要单独在类中配置初始化的方法)

5.将bean传递给后置处理器 调用初始化方法之后执行

6.正常使用bean对象

7.Spring容器关闭,调用该类的销毁回调的方法(需要单独在类中配置销毁的方法)

后置处理器底层原理

配置多个BeanPostProcessor

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;

public class MayiktBeanPost implements BeanPostProcessor, Ordered {
    /**
     * 调用初始化方法之前执行
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("调用该bean的 init方法之前");
        return bean;
    }

    /**
     * 调用初始化方法之后执行
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("调用该bean的 init方法之后");
        return bean;
    }

    public int getOrder() {
        return 1;
    }
}
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;

public class MayiktBeanPost02 implements BeanPostProcessor, Ordered {
    /**
     * 调用初始化方法之前执行
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("[MayiktBeanPost02:]调用该bean的 init方法之前");
        return bean;
    }

    /**
     * 调用初始化方法之后执行
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("[MayiktBeanPost02:]调用该bean的 init方法之后");
        return bean;
    }

    public int getOrder() {
        return 0;
    }
}
<!-- 后置处理器-->
<bean id="mayiktBeanPost" class="com.mayikt.bean.MayiktBeanPost"></bean>
<bean id="mayiktBeanPost02" class="com.mayikt.bean.MayiktBeanPost02"></bean>

实现Ordered接口 getOrder 值越小越优先加载

3.4.3、SpringBean的自动装配

什么是自动装配呢

根据装配的规则(属性的名称或者属性的类型)

Spring根据装配的规则自动为属性注入值。

1. 什么是自动装配

A. 根据指定装配规则(属性名称或者属性的类型),spring自动将匹配属性的值注入。

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

    <!-- spring ioc     <bean id="empEntity" class="com.mayikt.entity.EmpEntity">
        <property name="deptEntity" ref="deptEntity"></property>
    </bean> -->

    <!-- bean 标签中有一个属性autowire
         1.根据属性的名称注入 bean的id名称与属性的名称一致
         2.根据属性的类型注入 bean的类型与属性类型一致
      -->
    <bean id="empEntity" class="com.mayikt.entity.EmpEntity" autowire="byType">

    </bean>
    <bean id="deptEntity" class="com.mayikt.entity.DeptEntity">
        <property name="name" value="教育部门"></property>
    </bean>
  
</beans>

3.4.4、SpringBean的外部属性文件

3.5、SpringBean的注解形式

3.5.1、Spring的注解启动方式

Bean的管理操作方式

1. 基于XML方式实现

2. 基于注解方式实现

什么是注解:注解是JDK5中推出的新特性,代码的特殊标记,

格式注解名称“属性名称=属性值,属性名称=属性值”。

我们在后期学习springboot开发基本上都是使用注解,很少在使用

Xml配置的方式。

注解可以使用在类、方法、属性、上面。

使用注解的目的,简化xml的配置方式。

Spring提供的常用注解

1. @Component 将对象注入Spring容器中

2. @Service 注入业务逻辑对象

3. @Controller 控制器类

4. @Repository 注入dao对象

5. 以上该四个注解底层都是基于@Component注解封装的,只是区分用于

在不同的场景下。

注解的使用方式

AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext();
app.register(BeanConfig.class);
app.refresh();
MemberEntity  memberEntity = (MemberEntity) app.getBean("memberEntity");
System.out.println(memberEntity);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

出世&入世

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值