Spring(二)-生命周期 + 自动装配(xml) +自动装配(注解)

1、生命周期

Spring容器的 bean的生命周期;

Truck

@Data
@ToString
public class Truck {

    //品牌
    private String brand;
    //厂商
    private String factory;
    //价格
    private Double price;

    public Truck() {
        //空参构造方法,观察bean什么时候实例化
        System.out.println("------ 1.调用构造方法,创建实例对象 ------\n");
    }

    public void setBrand(String brand) {
        //任意一个set方法,观察bean什么时候注入参数
        System.out.println("------ 2.set方法,给实例对象赋值 ------");
        this.brand = brand;
    }

    public  void  initTruck(){
        //init初始化方法,观察bean什么时候初始化
        //需要再配置bean的时候,配置init初始化方法
        System.out.println("------ 3.Truck init 初始化方法 初始化对象 ------\n");
        this.brand = "大运";
    }

    public  void  destroyTruck(){
        //destory方法,观察bean什么时候销毁
        //需要再配置bean的时候,配置destory销毁方法
        System.out.println("------ 5.Truck destroy 销毁方法 销毁对象 ------\n");
    }
    //这里方法上标注的序号是测试后得来的;
}

spring-lifecycle.xml


public class TestSpringLifeCycle {

    //定义全局容器对象,如果需要关闭容器对象,
    //必须使用ApplicationContext的子接口 ConfigurableApplicationContext
    //ApplicationContext接口主要各种属性的get方法;
    //ConfigurableApplicationContext重在对各种属性的配置;

//    private ApplicationContext context;
    private ConfigurableApplicationContext context;

    @Before
    public void initApplicationContext(){
        context = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
    }

    //测试spring 容器的bean的生命周期,默认和加了处理器两种场景
    @Test
    public void  testSpringBeanLifeCycle(){

        //从容器中,获取Truck的是实例对象
        Truck truck = context.getBean("truck", Truck.class);

        //使用对象
        System.out.println("------ 4.使用容器中的bean对象"+truck +" ------");

        //关闭容器
        context.close();

    }

}

输出结果:

//可以得出 spring中bean的 默认生命周期



++++++ 初始化容器中的卡车对象 Truck(brand=大运, factory=安徽, price=200000.0)++++++

++++++ 3+1,后置处理器的的 after 方法 ++++++ ------ 2.set方法,给实例对象赋值 ------
++++++ 初始化后 处理后的 卡车对象 Truck(brand=after, factory=安徽, price=200000.0) ++++++

BeanPostProcessor官方定义为工厂钩子,我们也俗称 后置处理器。它 允许自定义修改新的bean实例,例如检查标记接口或用代理包装它们。应用程序上下文可以在其bean定义中自动检测BeanPostProcessor bean,并将它们应用于随后创建的任何bean。

BeanPostProcessor 的 前置处理后置处理

image-20220826150821502

2、自动装配(xml)

Person

@Data
public class Person {
    //昵称
    private String nickName;
    //车子
    private Car car;
    //房子
    private House house;
}

Car

@Data
public class Car {
    //品牌
    private String brand;
    //厂商
    private String factory;
    //价格
    private Double price;
}

House

@Data
public class House {
    //户型
    private  String type;
    //面积
    private double area;
    //价格
    private  Integer price;
}

autowire=”byType”:根据 属性 的 类型自动装配;

spring-auto.xml


public class TestSpringAutoUserXml {
    private ApplicationContext context;

    @Before
    public void initApplicationContext(){
        context = new ClassPathXmlApplicationContext("spring-auto.xml");
    }

    @Test
    public  void testSpringAuto(){
        Person person = context.getBean("person", Person.class);

        //使用对象
        System.out.println("容器中的person对象:"+person);

    }

}

输出结果:

容器中的person对象:Person(
                        nickName=huayu,
                        car=Car(brand=Bnw520, factory=华晨, price=450000.0),
                        house=House(type=三室一厅, area=96.0, price=2800000)
                        )

bean 配置:

其他不变,多增加一个Car类型的实例bean;


测试,报错信息:

No qualifying bean of type ‘com.kgc.spring.auto.Car’ available: expected single matching bean but found 2: car,carNew

总结:autowire=”byType” 当有 多个相同类型的bean时无法确定要装配的 bean;

其他配置信息不变,设置 autowire=”byName” ,根据 属性 的 名字 自动装配;


测试输出结果:

容器中的person对象:Person(
                        nickName=huayu,
                        car=Car(brand=Bnw520, factory=华晨, price=450000.0),
                        house=House(type=三室一厅, area=96.0, price=2800000)
                        )

总结

  • byType:根据类型自动装配:
  • 根据实体属性的 类型,到容器中,根据 bean类型 进行唯一匹配,如果可以匹配到对应类型的bean的实例,就会执行自动装配, 如果不能唯一匹配(同类型的bean有多个),会报错;
  • byName: 根据名称自动装配:
  • 根据 属性属性名,到容器中,根据 bean的id 属性值,进行唯一匹配,如果能够成功匹配,执行自动装配, 如果匹配不到,不执行自动装配,实体属性为null;

3、自动装配 (注解)

  • @Component 普通组件注解;
  • @Repository 持久层注解
  • @Service 业务层注解
  • @Controller 控制层注解

默认情况下:spring自动将分层组件(@Controller,@Service,@Repository,@component) 标识的类(不是接口), 自动创建实例对象放入容器中,使用bean的标识 id值为 对应 类名首字母小写 就相当于,帮我们手动添加了配置 :

如果 不想使用默认的类名首字母小写,我们可以使用注解的value属性执行一个自定义的id值;
比如:@Service(value=”自定义的id值”),注解只有value属性,可以省略value执行,简化为@Service(“自定义的id值”)

分层组件的目的,就仅仅是为了 方便开发人员明确当前注解 所在的类所对应的角色,在使用上, 建议使用,按照官方定义的使用,防止模糊不清;在springMVC框架中@Controller有特殊含义;

spring创建容器对象时,如果解析到 component-scan 组件扫描配置,会将base-package指定的基包(父包)及其子包所有增加了分层组件的类,自动创建实例,放进容器中;

配置文件


@Component
public class User {
    //用户名
    @Value("huayu") //@Value()  自动装配参数
    private  String userName;
    //用户密码
    @Value("123")
    private String userPwd;
}
@Test
public  void testSpringAutoUserAnnotation(){

    User user = context.getBean("user", User.class);

    System.out.println(user);
    //User(userName=huayu, userPwd=123)

}
@Component(value = "myUser")
public class User {
    //用户名
    private  String userName;
    //用户密码
    private String userPwd;
}
@Test
public  void testSpringAutoUserAnnotation(){

    //User user = context.getBean("user", User.class);
    //自定义id后,默认id不能使用: No bean named 'user' available

    //必须使用自定义id
    User user = context.getBean("myUser", User.class);

    System.out.println(user);
    //User(userName=huayu, userPwd=123)

}
  • 组件自动装配,可以实现 实体属性类型的自动装配,自动到spring的容器中,根据当前 属性的类型或者名称进行注入,如果容器中 能匹配到,就 直接将实例对象 注入到当前实体属性上,无序手动指定;
  • @Autowired自动装配原理:首先会根据byType方式,进行自动装配,
  • 如果 不能唯一匹配(存在同类型多个实例对象),会再次 尝试使用byName方式,根据当前实体属性名,到容器中进行匹配(容器中bean的id值),如果能唯一匹配,直接执行自动装配,
  • 默认情况下,@Autowired注解标识的实体属性,必须被装配
  • 如果 装配失败,就直接 抛出异常;
  • 如果 不需要校验必须被装配(项目启动,如果装配失败,项目是起不来);
  • 通过指定 required = false,去除必须执行自动装配的校验(即便容器中找不到装配的实例,也不会抛出异常);
  • 如果自动装配,容器中 存在多个同类型的bean对象,可以使用注解@Qualifier(“容器中同类型多个bean的某个id值”), 实现指定到容器中,找对应的bean实例对象,进行自动装配;
  • 底层是如何做的:在指定要扫描的包时,

People

@Data
@Component("myPeople")
public class People {
    //昵称
    @Value("huayu")
    private String name;
    //玩具
    @Autowired
    private Toy toy;

}

Toy接口

public interface Toy {
    //得到玩具
    public void getToy();

}

ToyImpl1

@Component("toy1")
public class ToyImpl1 implements Toy {

    @Value("玩具车")
    private String toyName;

    @Override
    public void getToy() {
        System.out.println(this.toyName);
    }
}

注意:可以 通过接口类型获取实现类(推荐使用);

@Test
public  void testAutowired  (){
    People people = context.getBean("myPeople", People.class);

    people.getToy().getToy(); //玩具车

}

当存在 多个相同类型的bean不能唯一匹配,会 自动装配错误

在写一个Toy实现类,ToyImpl2

@Component("toy2")
public class ToyImpl2 implements Toy {

    @Value("尤克里里")
    private String toyName;

    @Override
    public void getToy() {
        System.out.println(this.toyName);
    }

}

报错信息(项目无法启动):

No qualifying bean of type ‘com.kgc.spring.acnocation.bean.Toy’ available: expected single matching bean but found 2: toy1,toy2

主要信息:类型无法唯一匹配;

People

@Data
@Component("myPeople")
public class People {

    //昵称
    @Value("huayu")
    private String name;

    //玩具
    @Autowired (required = false)
    private Toy toy;

}

项目可以启动但是还是报错(一般项目中不会有两个相同类型的实现类;)

People

@Data
@Component("myPeople")
public class People {

    //昵称
    @Value("huayu")
    private String name;

    //玩具
    @Autowired
    @Qualifier("toy2") //指定bean的id值
    private Toy toy;

}
@Test
public  void testAutowired  (){
    People people = context.getBean("myPeople", People.class);

    System.out.println(people.getToy());
    //com.kgc.spring.acnocation.bean.ToyImpl2@15d9bc04

    people.getToy().getToy();
    //尤克里里

}

include-filter

指定扫描(包含扫描):

  • 只会扫描指定的 或者 某类组件(使用分组扫描), 加入到容器中;
  • 但是 必须配合父标签的 user-default-filter使用,默认值是true,就是全部扫描;
  • 指定扫描,如果要生效 必须改为false
  • 指定扫描 某类组件,type=”annotation” expression=”某类组件注解的全类名”;
  • 指定扫描 某个类,type=”assignable” expression=”某个类的全类名”;

type=”annotation”

  • org.springframework.stereotype.Component
  • org.springframework.stereotype.Repository
  • org.springframework.stereotype.Service
  • org.springframework.stereotype.Controller

type=”assignable”


exclude-filter

  • 排除扫描(剔除扫描):排除指定的 某类组件不加入到容器中,处理排除外的其他组件,仍然会被添加到容器中;
  • 不需要配合父标签,use-default-filters=”true” 因为,默认就是在全部扫描的基础上剔除;
  • 排除扫描 某类组件,type=”annotation” expression=”某类组件注解的全类名”;
  • 排除扫描 某个类,type=”assignable” expression=”某个类的全类名”;

type=”annotation”


type=”assignable”


Original: https://www.cnblogs.com/xiaoqigui/p/16632269.html
Author: 化羽羽
Title: Spring(二)-生命周期 + 自动装配(xml) +自动装配(注解)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/621536/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 多商户商城系统功能拆解31讲-平台端营销-会员充值

    多商户商城系统,也称为B2B2C(BBC)平台电商模式多商家商城系统。可以快速帮助企业搭建类似拼多多/京东/天猫/淘宝的综合商城。 多商户商城系统支持商家入驻加盟,同时满足平台自营…

    数据库 2023年6月14日
    072
  • 钻石价格预测的ML全流程!从模型构建调优道部署应用!⛵

    💡 作者:韩信子@ShowMeAI📘 数据分析 ◉ 技能提升系列:http://www.showmeai.tech/tutorials/33📘 AI 面试题库系列:http://w…

    数据库 2023年6月15日
    084
  • vim+vundle配置

    Linux环境下写代码虽然没有IDE,但通过给vim配置几个插件也足够好用。一般常用的插件主要包括几类,查找文件,查找符号的定义或者声明(函数,变量等)以及自动补全功能。一般流程都…

    数据库 2023年6月9日
    080
  • [springmvc]ajax异步请求数据详细简单

    10.Ajax异步请求 Ajax即 Asynchronous Javascript And XML(异步JavaScript和XML在 2005年被Jesse James Garr…

    数据库 2023年6月16日
    071
  • Java架构师电商项目(220h):1-1 整体架构概述

    2022 Flag:学完这门 220h Java架构师电商项目视频课学习笔记将持续更新…… ; 大型网站特点 高并发 高可用 大数据 迭代周期短 用户量庞大…

    数据库 2023年6月6日
    078
  • CentOS7.2解决vsftpd启动失败,code=exited,status=2问题的几个方法参考

    【问题说明】重启vsftpd服务失败:[root@data ~]# systemctl restart vsftpdJob for vsftpd.service failed. S…

    数据库 2023年6月14日
    0320
  • 猴子吃桃(递归)

    递归案例实践分析 猴子偷桃 题目描述: 猴子第一天摘下若干桃子,当即吃了一半,觉得好吃不过瘾,于是又多吃了一个,,第二天又吃了前天剩余桃子数量的一半,觉得好不过瘾,于是又多吃了一个…

    数据库 2023年6月16日
    0146
  • Ubuntu 服务器安装 MySQL 远程数据库

    在 Web 项目中,我们需要使用到远程数据库,开发阶段也需要连接并查看数据库的状况。腾讯云、阿里云等云平台提供了远程数据库,可直接使用;当然也可以自己在部署 Web 的服务器上安装…

    数据库 2023年5月24日
    062
  • 代码优化记录

    代码优化记录 神龟虽寿,犹有竟时。 神龟虽寿 犹有竟时 Original: https://www.cnblogs.com/taojietaoge/p/15853508.htmlA…

    数据库 2023年6月14日
    085
  • Pisanix v0.2.0 发布|新增动态读写分离支持

    1.动态读写分离介绍 1.1 介绍 读写分离是业界使用 MySQL 高可用最常用的方案之一,在实际场景中可以提高查询性能,降低服务器负载。本次版本在 v0.1.0 静态规则基础上增…

    数据库 2023年6月16日
    082
  • rsync

    rsync是什么 rsync特性 1)可以镜像保存整个目录树和文件系统。 2)可以很容易做到保持原来文件的权限、时间、软硬连接等。 3)无需特殊权限即可安装。 4)快速:第一次同步…

    数据库 2023年6月14日
    076
  • Spring(三)-AOP

    1、名词理解 切面(Aspect): 含有前置通知,后置通知,返回通知,异常抛出通知,环绕通知等方法的 类; 通知(Advice): 对原方法进行添加处理(如日志等)的 方法; 切…

    数据库 2023年6月16日
    071
  • 关于Mysql索引的数据结构

    索引的数据结构 1、为什么使用索引 概念: 索引是存储索引用于快速找到数据记录的一种数据结构,就好比一本书的目录部分,通过目录中对应的文…

    数据库 2023年5月24日
    086
  • SQL语句的整合

    基础语法 https://blog.csdn.net/m0_37989980/article/details/103413942 CRUD 提供给数据库管理员的基本操作,CRUD(…

    数据库 2023年6月14日
    067
  • MySQL之连接查询和子查询

    多表连接的基本语法 多表连接,即将多个表拼接成一个表,然后进行查询 [En] Multi-table join, that is, several tables are splic…

    数据库 2023年5月24日
    0131
  • IDEA中tomcat插件版本7中文乱码问题

    tomcat插件版本7中文乱码问题 IDEA中tomcat插件版本7中文乱码问题 问题描述: 因为idea中tomcat插件版本只到7,他的默认解码方式为:ISO-8859-1,又…

    数据库 2023年6月16日
    071
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球