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

3.3、SpringBean的注入方式

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

1. 什么是Bean管理

使用spring创建对象

使用spring注入属性

2. Bean的管理有两种方式

1. 基于XML方式配置

基于XML方式创建对象

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

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

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

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

2. 基于xml方式注入属性

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

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


    
    

在Bean标签下 在定义一个属性标签
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配置文件


 
    
    

指定参数列表名称

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

3.3.3、p名称空间注入

1. Xml头部引入P标签


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


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

3.3.4、注入空值和特殊符号

注入空值属性


    
    
    
        
    

注入特殊符号

转移注入方式

<< 转移为:<<

>>转移为:>>


    
    
    
        
    

Cdata注入方式

>]]>


    
    
        >]]>
    
    
        
    

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("<<>");
        // 原始的方式
//        MemberDao memberDao = new MemberDaoImpl();
//        memberDao.addMember();
        memberDao.addMember();
    }
}




    
    
        
        
    
    

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相关配置



    
    
    
    
    
        
            
        
    

3.3.7、注入级联赋值

写法1


    
    
    
    
    


    

写法2


    
    
    
    
    
    


注意:需要在员工实体类新增: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 list;
    //3.Map
    private Map map;
    //4.Set
    private Set set;

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

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

    public void setMap(Map map) {
        this.map = map;
    }

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

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

配置文件


    
    
        
            mayikt01
            mayikt02
        
    
    
    
        
            语文
            数学
        
    
    
    
       
           
           
       
    
    
    
       
           01
           02
       
    

集合类型为对象

private List courses;
public void setCourses(List 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 + '\'' +
                '}';
    }
}



    
        
        
            
                list01
                list02
            
        
        
        
            
                mayikt01
                mayikt02
            
        
        
        
            
                
                
            
        
        
        
            
                list01
                list02
            
        
        
            
                
           

集合注入部分提取公共

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


2. 使用util标签 注入




    
    
        mayikt01
        mayikt02
    
    
        
    

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 {
    /**
     * 定义返回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存在多个实例;

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

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

单例配置:

默认就是为单例子;

多例配置:

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方法");
    }
}

   

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

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


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

3.4.3、SpringBean的自动装配

什么是自动装配呢

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

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

1. 什么是自动装配

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




    

    
    

    
    
        
    
  

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

你可能感兴趣的:(JavaWeb,Java,spring,java,后端,bean,web)