网站建设番禺,泉州关键词搜索排名,敬请期待下一句怎么对,网站添加百度商桥文章目录 #x1f49e; 官方资料#x1f34a;Spring5下载#x1f34a;文档介绍 #x1f49e;Spring5#x1f34a;内容介绍#x1f34a;重要概念 #x1f49e;快速入门#x1f34a;Spring操作演示#x1f34a;类加载路径#x1f34a;Debug配置#x1f34a;Spring容器… 文章目录 官方资料Spring5下载文档介绍 Spring5内容介绍重要概念 快速入门Spring操作演示类加载路径Debug配置Spring容器结构剖析 实现简单基于XML配置程序Spring原生容器结构梳理作业布置 基于XML配置Bean通过类型获取bean通过指定构造器配置bean通过p名称空间配置bean通过ref配置bean通过内部bean配置属性对集合数组属性进行配置使用utillist进行配置属性级联赋值配置通过静态工厂获取beanbean配置信息重用bean创建顺序bean的单例和多实例bean的生命周期配置bean后置处理器通过属性文件配置bean基于XML的bean的自动装配Spring El 表达式配置Bean 官方资料 Spring5下载 进入官网: https://spring.io/进入Spring5(框架就是一系列jar包. 引入jar包, 就可以使用spring) 进入Spring5的github(Spring本身也是GitHub的开源项目) 下拉找到Access to Binaries, 进入Spring Framework Artifacts 进入到Spring的仓库(这里有Spring的各个版本的jar包) 具体路径 snapshot-org-springframework-spring 下载网址 https://repo.spring.io/artifactory/snapshot/org/springframework/spring/ 资源已上传, 如下 文档介绍 在线文档https://docs.spring.io/spring-framework/reference/离线文档spring-framework-5.3.8\docs\reference\html\index.html离线APIspring-framework-5.3.8\docs\javadoc-api\index.html Spring5 内容介绍 Spring核心学习内容 IOC, AOP, jdbcTemplate, 声明式事务 IOC: 控制反转, 可以管理java对象AOP: 切面编程JDBCTemplate: 是spring提供的一套访问数据库的技术. 应用性强, 相对好理解声明式事务: 基于ioc/aop实现事务管理IOC, AOP 是重点同时是难点, 需要时间理解 重要概念 Spring可以整合其它的框架(解读: Spring是管理框架的框架) Spring有两个核心的概念: IOC 和 AOP IOC [Inversion Of Control 反转控制] 传统的开发模式[JDbcUtils / 反射], 程序------环境 //程序读取环境配置, 然后自己创建对象 以连接到数据库为例 程序员编写程序, 在程序中读取配置信息 创建对象, 使用对象完成任务 Spring方式 Spring根据配置文件xml / 注解, 创建对象, 并放入到容器(ConcurrentHashMap). 并且可以完成对象之间的依赖 当需要使用某个对象实例的时候, 就直接从容器中获取即可 这样程序员可以更加关注如何使用对象完成相应的业务(以前是new - 现在是注解 / 配置) DI - Dependency Injection依赖注入, 可以理解成是IOC的别称 Spring最大的价值是 通过配置, 给程序员提供需要使用的对象web层[Servlet (Action/Controller)/ Service / Dao / JavaBean(entity)]对象 这是核心价值所在, 也是ioc的具体体现, 实现解耦 快速入门 Spring操作演示 需求: 通过Spring的方式[配置文件], 获取JavaBean-Monster的对象, 并给该对象的属性赋值, 输出该对象的信息 下载Spring5开发包, Spring5开发包资源博主已上传创建Java工程, Spring5 新建lib目录, 引入开发Spring5的基本包 创建JavaBean, 一定要有无参构造器. Spring底层反射创建对象时, 需要使用 package com.zzw.spring.bean;
public class Monster {private String monsterId;private String name;private String skill;//无参构造器: Spring底层反射创建对象时, 需要使用public Monster() {}//有参构造器, setter, getter, toString()
}src目录下: 新建一个容器配置文件beans.xml 创建好之后, 右上角进行配置, 默认的就行 xmlns表示xml namespace, 即xml命名空间 ?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd!--1.配置monster对象/javabean2.在beans中可以配置多个bean3.bean表示一个java对象4.class是用于指定类的全路径-Spring底层使用反射创建(所以要有无参构造器)5.id属性表示该java对象在spring容器中的id, 通过id可以获取到该对象6.property namemonsterId value100/ 用于给该对象的属性赋值, String没有赋值就是null--bean classcom.zzw.spring.bean.Monster idmonster01property namemonsterId value100/property namename value美猴王/property nameskill value金箍棒//bean
/beans测试 package com.zzw.spring.test;public class SpringBeanTest {Testpublic void getMonster() {//解读//1.创建容器 ApplicationContext//2.该容器和容器配置文件关联//3.习惯用接口的形式接收ApplicationContext ioc new ClassPathXmlApplicationContext(beans.xml);//3.通过getBean获取对应的对象// 默认返回的是Object, 但是运行类型是Monster//Object monster01 ioc.getBean(monster01);Monster monster01 (Monster) ioc.getBean(monster01);//4.输出System.out.println(monster01 monster01 , monster01运行类型 monster01.getClass());System.out.println(monster01 monster01 , 属性name monster01.getName() , monsterId monster01.getMonsterId());//5.也可以在获取的时候, 直接指定Class类型, 可以再次获取Monster monster011 ioc.getBean(monster01, Monster.class);System.out.println(monster011 monster011);System.out.println(monster011.name monster011.getName());System.out.println(ok~~~);}
}类加载路径 解释类加载路径 ClassPathXmlApplicationContext ioc new ClassPathXmlApplicationContext(“beans.xml”); //验证类加载路径
Test
public void classPath() {File file new File(this.getClass().getResource(/).getPath());//看到类的加载路径System.out.println(file file);
}Debug配置 Spring容器结构剖析 判断是否是懒加载: 是事先创建好, 还是等到用户使用的时候再创建. lazyInit: false. 说明beans.xml中对象的创建不是懒加载. 用Debug的方式, 看一下Spring容器的处理机制 ioc-beanFactory-beanDefinitionMap beanDefinitionMap / table index217 table / propertyValues beanFactory-singletonObjects singletonObjects / table beanFactory / beanDefinitionNames 题目: 查看容器注入了哪些bean对象, 输出bean的id String[] beanDefinitionNames ioc.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {System.out.println(beanDefinitionName beanDefinitionName);
}实现简单基于XML配置程序 需求说明 自己写一个简单的Spring容器, 通过读取beans.xml, 获取第1个JavaBean: Monster的对象, 并给该对象的属性赋值, 放入到容器中, 并输出该对象信息也就是说, 不使用Spring原生框架, 我们自己简单模拟实现了解Spring容器的简单机制 思路分析 实现 引入dom4j-1.6.1.jar包 ZzwApplicationContext.java package com.zzw.spring.zzwapplicationcontext;/*** author 赵志伟* version 1.0* 1.这个程序用于实现Spring的一个简单容器机制* 2.后面还会详细实现* 3.这里我们实现如何将beans.xml文件进行解析, 并生成对象, 放入容器中* 4.提供一个方法 getBean(id) 返回对应的对象* 5.这里就是一个开胃小点心, 理解Spring容器的机制*/
SuppressWarnings({all})
public class ZzwApplicationContext {private ConcurrentHashMapString, Object singletonObjects new ConcurrentHashMap();//构造器//接收一个容器的配置文件 比如 beans.xml, 该文件默认在src目录下public ZzwApplicationContext(String iocBeanXmlFile) throws Exception {//1.得到类加载路径:// /D:/idea_project/zzw_spring/spring/out/production/spring/String path this.getClass().getResource(/).getPath();//2.创建解析器SAXReader reader new SAXReader();//3.得到document对象Document document reader.read(new File(path iocBeanXmlFile));//4.获取rootElementElement rootElement document.getRootElement();//5.得到第1个bean-monster01Element bean (Element) rootElement.elements(bean).get(0);//6.获取第一个bean-monster01的相关属性 beanDefinitionMapString id bean.attributeValue(id);String ClassFullPath bean.attributeValue(class);ListElement properties bean.elements(property);//这里不再遍历, 直接获取Integer monsterId Integer.parseInt(properties.get(0).attributeValue(value));String name properties.get(1).attributeValue(value);String skill properties.get(2).attributeValue(value);//7.使用反射创建对象 回顾反射机制Class? aClass Class.forName(ClassFullPath);//这里instance就是Monster对象Monster o (Monster) aClass.newInstance();//给o对象通过反射来赋值 这里先简化o.setMonsterId(monsterId);o.setName(name);o.setSkill(skill);//8.将创建好的对象放入到singletonObjectssingletonObjects.put(id, o);}public Object getBean(String id) {//这里可以再处理一下return singletonObjects.get(id);}
}测试 ZzwApplicationContextTest package com.zzw.spring.zzwapplicationcontext;public class ZzwApplicationContextTest {public static void main(String[] args) throws Exception {ZzwApplicationContext ioc new ZzwApplicationContext(beans.xml);Monster monster01 (Monster) ioc.getBean(monster01);System.out.println(monster01 monster01);System.out.println(monster01.name monster01.getName());System.out.println(ok~);}
}Spring原生容器结构梳理 作业布置 在beans.xml中, 注入两个Monster对象, 但是不指定id, 运行会不会报错? 如果不会报错, 如果知道id, 并获取Monster对象. 不会报错, 会正常运行系统会默认分配id. 分配id的规则是: 全类名#0, 全类名#1 这样的规则来分配id的. 例如 com.zzw.spring.bean.Monster#0, com.zzw.spring.bean.Monster#1通过debug方式来查看 public class homework01 {Testpublic void getMonster() {//1.创建容器, 习惯用接口的形式接收ApplicationContext ioc new ClassPathXmlApplicationContext(beans.xml);Monster monster1 ioc.getBean(com.zzw.spring.bean.Monster#0, Monster.class);System.out.println(monster1 monster1);Monster monster2 ioc.getBean(com.zzw.spring.bean.Monster#1, Monster.class);System.out.println(monster2 monster2);System.out.println(ok~);}
}创建一个Car类, 要求 创建ioc容器文件(配置文件), 并配置一个Car对象(bean).通过java程序到ioc容器获取该bean对象, 并输出 public class Car {private Integer id;private String name;private Double price;public Car() {System.out.println(car对象 无参构造器被执行);}//有参构造器, setter, getter, toString()beans1.xml ?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd!--配置carbean--bean classcom.zzw.spring.bean.Car idcar01property nameid value100/property namename value奔驰/property nameprice value120000.00//bean
/beanspublic class homework02 {public static void main(String[] args) {//1.创建容器对象ApplicationContext ioc new ClassPathXmlApplicationContext(beans1.xml);Car car01 ioc.getBean(car01, Car.class);System.out.println(car01 car01);System.out.println(car01.name car01.getName());System.out.println(ok~);}
}基于XML配置Bean Bean管理包括两方面: 创建bean对象, 给bean注入属性 通过类型获取bean 案例: 通过spring的ioc容器, 获取一个bean对象, 获取方式: 按类型. !--配置Monster, 通过类型获取--
bean classcom.zzw.spring.bean.Monster!--解读1.当我们给某个bean对象设置属性的时候2.底层是使用对应的setter方法完成的, 比如setName()3.如果没有这个方法, 就会报错--property namemonsterId value100/property namename value孙悟空/property nameskill value火眼金睛/
/bean演示通过bean的类型获取对象 Test
public void getBeanByType() {ApplicationContext ioc new ClassPathXmlApplicationContext(beans.xml);//直接传入class对象/类型Monster bean ioc.getBean(Monster.class);System.out.println(bean bean);
}细节 按照类型获取bean, 要求ioc容器中的同一个类的bean只能有一个, 否则会抛出异常 NoUniqueBeanDefinationException 这种方式的应用场景: 比如XxxAction / Servlet / Controller, 或XxxService在一个线程中只需要一个对象实例(单例)的情况 在容器配置文件(比如beans.xml)中给属性赋值. 底层是通过setter方法完成的. 所以需要提供setter方法. 通过指定构造器配置bean !--配置Monster对象, 并且指定构造器--
!--
解读
1.constructor-arg标签可以指定使用构造器的参数
2.index表示构造器的第几个参数, 从0开始计算的
3.除了可以通过index, 还可以通过name / type来指定参数方式
4.解除大家的疑惑: 类的构造器, 不能有完全相同类型和顺序的构造器, 所以可以通过type来指定一个类中的两个构造器, 参数的类型和顺序不能完全相同可以类型相同, 但顺序不同
--
bean classcom.zzw.spring.bean.Monster idmonster03constructor-arg value100 index0/constructor-arg value齐天大圣 index1/constructor-arg value如意金箍棒 index2/
/beanbean classcom.zzw.spring.bean.Monster idmonster04constructor-arg value200 namemonsterId/constructor-arg value斗战胜佛 namename/constructor-arg value无法无天 nameskill/
/beanbean classcom.zzw.spring.bean.Monster namemonster05constructor-arg value300 typejava.lang.Integer/constructor-arg value猪悟能 typejava.lang.String/constructor-arg value追嫦娥~ typejava.lang.String/
/bean演示通过构造器来设置属性 Test
public void setBeanByConstructor() {ApplicationContext ioc new ClassPathXmlApplicationContext(beans.xml);Monster monster03 ioc.getBean(monster03, Monster.class);System.out.println(monster03 monster03);
}通过index属性来区分是第几个参数; 通过type属性来区分是什么类型(按照顺序, 这是可以的) 通过p名称空间配置bean xmlns:p“http://www.springframework.org/schema/p” !--通过p名称空间来配置bean将光标放在p这个位置, 输入altenter, 就会自动的添加xmlns. 有时需要多来几次, 有个识别的过程
--
bean classcom.zzw.spring.bean.Monster idmonster06p:monsterId400p:name天蓬元帅p:skill掌管十万天军
/演示通过p名称空间来设置属性 public class SpringBeanTest {Testpublic void setBeanByP() {ApplicationContext ioc new ClassPathXmlApplicationContext(beans.xml);Monster monster06 ioc.getBean(monster06, Monster.class);System.out.println(monster06 monster06);}
}通过ref配置bean 引用注入其它bean对象 在spring的ioc容器, 可以通过ref来实现bean对象的相互引用[ref全称: reference] !--配置MemberDaoImpl对象--
bean classcom.zzw.spring.dao.MemberDaoImpl idmemberDao/
!--配置MemberServiceImpl对象1.refmemberDao表示 MemberServiceImpl对象属性memberDao引用的对象是idmemberDao的对象2.这里就体现出spring容器的依赖注入3.注意: 在spring容器中, 它是作为一个整体来执行的, 即如果引用到了一个bean对象, 对配置的顺序没有要求4.建议还是按顺序. 好处是在阅读的时候, 比较方便
--
bean classcom.zzw.spring.service.MemberServiceImpl idmemberServiceproperty namememberDao refmemberDao/
/beanpackage com.zzw.spring.service;public class MemberServiceImpl {private MemberDaoImpl memberDao;public MemberDaoImpl getMemberDao() {return memberDao;}public void setMemberDao(MemberDaoImpl memberDao) {this.memberDao memberDao;}public void add() {System.out.println(MemberServiceImpl add方法被调用...);memberDao.add();}
}package com.zzw.spring.dao;public class MemberDaoImpl {public MemberDaoImpl() {System.out.println(MemberDaoImpl 构造器...);}public void add() {System.out.println(MemberDaoImpl add方法被执行);}
}通过ref来设置bean属性 public class SpringBeanTest {Testpublic void setBeanByRef() {ApplicationContext ioc new ClassPathXmlApplicationContext(beans.xml);MemberServiceImpl memberService ioc.getBean(memberService, MemberServiceImpl.class);memberService.add();}
}通过内部bean配置属性 引用/注入内部bean对象 在spring的ioc容器, 可以直接配置内部bean对象 !--配置MemberServiceImpl对象-使用内部bean--
bean classcom.zzw.spring.service.MemberServiceImpl idmemberService2!--自己配置一个内部bean--property namememberDaobean classcom.zzw.spring.dao.MemberDaoImpl//property
/bean通过内部bean, 设置属性 public class SpringBeanTest {Testpublic void setBeanByPro() {ApplicationContext ioc new ClassPathXmlApplicationContext(beans.xml);MemberServiceImpl memberService2 ioc.getBean(memberService2, MemberServiceImpl.class);memberService2.add();}
}对集合数组属性进行配置 引用/注入 集合/数据类型 主要掌握List / Map / Properties 三种集合的使用Properties是Hashtable的子类, 是key-value的形式这里的properties的k-v, 都是String类型 在spring的ioc容器中, 如何给bean对象的 集合/数组 类型的属性赋值 public class Master {private String name;//主人名字private ListMonster monsterList;private MapString, Monster monsterMap;private SetMonster monsterSet;//数组private String[] monsterName;//Java基础//这个Properties 是HashMap的子类, 是key-value的存放形式//这里Properties key和value 都是Stringprivate Properties properties;//getter, setter方法
}给集合/数组属性进行赋值 public class SpringBeanTest {Testpublic void setBeanByCollection() {ApplicationContext ioc new ClassPathXmlApplicationContext(beans.xml);Master master ioc.getBean(master, Master.class);System.out.println(master master);}
}对List属性进行配置 !--配置Master对象
体会spring容器配置的特点 依赖注入
--
bean classcom.zzw.spring.bean.Master idmasterproperty namename value太上老君/!--给list属性赋值--property namemonsterListlist!--引用的方式加入的--ref beanmonster03/ref beanmonster04/!--内部bean, 不再建议id--bean classcom.zzw.spring.bean.Monsterp:monsterId300p:name狮驼岭p:skill紫金葫芦//list/property
/bean对Map属性进行配置 !--配置Master对象
体会spring容器配置的特点 依赖注入 非常灵活
--
bean classcom.zzw.spring.bean.Master idmasterproperty namename value太上老君/!--给map属性赋值--property namemonsterMapmapentrykeyvaluemonster04/value/key!--这里使用的是外部的bean, 引入--ref beanmonster04//entryentrykeyvaluemonster03/value/key!--内部bean, 不再建议id--bean classcom.zzw.spring.bean.Monsterp:monsterId300p:name狮驼岭p:skill紫金葫芦~//entry/map/property
/bean对Set属性进行配置 !--配置Master对象
体会spring容器配置的特点 依赖注入 非常灵活
--
bean classcom.zzw.spring.bean.Master idmasterproperty namename value太上老君/!--给set属性赋值--property namemonsterSetset!--这里使用的是外部的bean, 引入--ref beanmonster05/ref beanmonster06/!--内部bean, 不再建议id--bean classcom.zzw.spring.bean.Monsterp:monsterId300p:name狮驼岭p:skill紫金葫芦~//set/property
/bean对Array属性进行配置 !--配置Master对象
体会spring容器配置的特点 依赖注入 非常灵活
--
bean classcom.zzw.spring.bean.Master idmasterproperty namename value太上老君/!--给数组属性赋值补充: array标签中使用 value 还是 bean, ref ...要根据业务来决定这里的monsterName是字符串--property namemonsterNamearrayvalue六耳猕猴/valuevalue东海龙王/valuevalue红孩儿/value/array/property
/bean对Properties属性进行配置 !--配置Master对象
体会spring容器配置的特点 依赖注入 非常灵活
--
bean classcom.zzw.spring.bean.Master idmasterproperty namename value太上老君/!--对properties属性进行赋值 结构k(String)-v(String) --property namepropertiespropsprop keyusernameroot/propprop keypassword123456/propprop keyemail978964140qq.com/prop/props/property
/bean使用utillist进行配置 spring的ioc容器, 可以通过util名称空间来创建list集合 public class BookStore {//书private ListString bookList;//无参构造器, 如果没有其它的构造器, 该无参构造器可以不写//如果有其它的构造器, 则必须显示地定义一下无参构造器public BookStore() {}//getter, setter方法
}beans.xml !--定义一个util:list, 并且指定了id 可以达到数据复用
说明: 在使用util:list 名称空间的时候, 需要引入相应的标签, 一般来说通过altenter会自动加入
, 如果没有就手动添加一下
--
util:list idmyBookListvalue三体/valuevalue时间简史/valuevalue梦的解析/valuevalue福尔摩斯探案集/value
/util:list!--配置BookStore对象--
bean classcom.zzw.spring.bean.BookStore idbookStoreproperty namebookList refmyBookList/
/bean使用util:list名称空间给属性赋值 public class SpringBeanTest {Testpublic void setBeanByUtilList() {ApplicationContext ioc new ClassPathXmlApplicationContext(beans.xml);BookStore bookStore ioc.getBean(bookStore, BookStore.class);System.out.println(bookStore bookStore);}
}属性级联赋值配置 spring的ioc容器, 可以直接给对象属性的属性赋值, 即级联属性赋值 部门 public class Dept {private String name;public Dept() {}//getter, setter方法员工 public class Employee {private String name;private Dept dept;public Employee() {}//getter, setter方法
}beans.xml !--配置Dept对象--
bean classcom.zzw.spring.bean.Dept iddept/
!--配置Employee对象--
bean classcom.zzw.spring.bean.Employee idemployeeproperty namename valuetom/property namedept refdept/!--这里我希望给dept的name属性指定值[级联属性赋值]--property namedept.name valuejava开发/
/bean给属性进行级联赋值 public class SpringBeanTest {Testpublic void setBeanByRelation() {ApplicationContext ioc new ClassPathXmlApplicationContext(beans.xml);Employee employee ioc.getBean(employee, Employee.class);System.out.println(employee employee);}
}通过静态工厂获取bean 在spring的ioc容器, 可以通过静态工厂获取bean对象 这是一个静态工厂类-可以返回Monster对象 package com.zzw.spring.factory;public class MyStaticFactory {private static MapString, Monster monsterMap;//使用static代码块进行初始化 - java基础static {monsterMap new HashMap();monsterMap.put(monster01, new Monster(100, 齐天大圣, 如意金箍棒));monsterMap.put(monster02, new Monster(200, 天蓬元帅, 九齿钉耙));}//提供一个方法, 返回Monster对象public static Monster getMonster(String key) {return monsterMap.get(key);}
}!--配置Monster对象, 通过静态工厂获取
解读
1.通过静态工厂获取bean
2.class 是静态工厂类的全路径
3.factory-method 表示是指定静态工厂类的哪个方法返回对象
4.constructor-arg valuemonster02 value是指定要返回静态工厂的哪一个对象
--
bean classcom.zzw.spring.factory.MyStaticFactory idmyMonster01factory-methodgetMonsterconstructor-arg valuemonster02/
/bean通过静态工厂获取bean public class SpringBeanTest {Testpublic void getBeanByStaticFactory() {ApplicationContext ioc new ClassPathXmlApplicationContext(beans.xml);Monster myMonster01 ioc.getBean(myMonster01, Monster.class);Monster myMonster02 ioc.getBean(myMonster01, Monster.class);System.out.println(myMonster01 myMonster01);System.out.println(myMonster01 myMonster02);//true. myMonster01和myMonster02是同一个对象}
}bean配置信息重用 在spring的ioc容器, 提供了一种继承的方式来实现bean配置信息的重用 !--配置Monster对象--
bean classcom.zzw.spring.bean.Monster idmonster10p:monsterId10p:name蜘蛛侠p:skill吐丝
/
!--1.配置Monster对象,2.但是这个对象的属性值和idmonster10对象的属性值一样3.parentmonster10 指定当前这个配置的对象的属性值从 idmonster10的对象来
--
bean classcom.zzw.spring.bean.Monster idmonster11 parentmonster10/!--配置Monster对象
1.如果bean指定了 abstracttrue, 表示该bean对象, 是用于被继承
2.本身这个bean就不能被获取/实例化
--
bean classcom.zzw.spring.bean.Monster idmonster12 abstracttruep:monsterId12p:name蜘蛛侠~p:skill吐丝~
/
bean idmonster13 classcom.zzw.spring.bean.Monster parentmonster12/通过继承, 配置bean public class SpringBeanTest {Testpublic void getBeanByExtends() {ApplicationContext ioc new ClassPathXmlApplicationContext(beans.xml);Monster monster11 ioc.getBean(monster11, Monster.class);System.out.println(monster11 monster11);Monster monster13 ioc.getBean(monster13, Monster.class);System.out.println(monster13 monster13);}
}bean创建顺序 在spring的ioc容器, 默认是按照配置的顺序创建bean对象 测试bean创建顺序 public class SpringBeanTest {Testpublic void testBeanCreateOrder() {ApplicationContext ioc new ClassPathXmlApplicationContext(beans.xml);System.out.println(ok~);}
}实验1 public class Department {public Department() {System.out.println(Department构造器 被执行);}
}public class Student {public Student() {System.out.println(Student构造器 被执行);}
}※会先创建student01这个bean对象, 然后创建department01这个bean对象 执行结果: Student构造器 被执行 Department构造器 被执行 ok~ !--测试bean对象的创建顺序
1.在默认情况下, bean创建的顺序是按照配置顺序来的
2.但是如果我们增加了 depends-ondepartment01 这时就会先创建iddepartment01这个对象
--
bean classcom.zzw.spring.bean.Student idstudent01/
bean classcom.zzw.spring.bean.Department iddepartment01/※如果这样配置, 会先创建department01对象, 再创建student01对象 执行结果: Department构造器 被执行 Student构造器 被执行 ok~ !--测试bean对象的创建顺序
1.在默认情况下, bean创建的顺序是按照配置顺序来的
2.但是如果我们增加了 depends-ondepartment01 这时就会先创建iddepartment01这个对象
--
bean classcom.zzw.spring.bean.Student idstudent01 depends-ondepartment01/
bean classcom.zzw.spring.bean.Department iddepartment01/实验2 1.先看下面的配置, 请问两个bean创建的顺序是什么? 并分析执行流程 先创建 idmemberDao再创建 idmemberService调用 memberService.setMemberDao() 完成引用 运行结果: MemberDaoImpl 构造器… MemberServiceImpl 构造器被执行 setMemberDao()… !--配置MemberDaoImpl对象--
bean classcom.zzw.spring.dao.MemberDaoImpl idmemberDao/bean classcom.zzw.spring.service.MemberServiceImpl idmemberServiceproperty namememberDao refmemberDao/
/bean2.先看下面的配置, 请问两个bean创建的顺序是什么? 并分析执行流程 先创建 idmemberService再创建 idmemberDao调用 memberService.setMemberDao() 完成引用 运行结果: MemberServiceImpl 构造器被执行 MemberDaoImpl 构造器… setMemberDao()… bean classcom.zzw.spring.service.MemberServiceImpl idmemberServiceproperty namememberDao refmemberDao/
/bean!--配置MemberDaoImpl对象--
bean classcom.zzw.spring.dao.MemberDaoImpl idmemberDao/bean的单例和多实例 在spring的ioc容器中, 默认情况下是按照单例创建的. 即配置一个bean对象后, ioc容器只会创建一个bean对象 如果我们希望ioc容器配置的某个bean对象, 是以多个实例形式创建的. 则可以通过配置 scope“prototype” 来指定 public class Cat {private Integer id;private String name;public Cat() {//getter, setter方法
}!--配置Cat对象
1.在默认情况下, scope属性是 scopesingleton
2.在ioc容器中, 只会有一个这样的bean对象
3.当程序员执行getBean时, 返回的是同一个对象
4.如果我们希望每次返回一个新的bean对象, 则可以这样配置 scopeprototype
5.如果bean的配置是 scopesingleton lazy-inittrue 这时, ioc容器就不会提前创建该对象, 而是当执行getBean方法的时候, 才会创建对象
--
bean classcom.zzw.spring.bean.Cat idcat scopeprototype lazy-inittrueproperty nameid value100/property namename value花喵/
/bean测试Scope Test
public void testBeanScope() {ApplicationContext ioc new ClassPathXmlApplicationContext(beans.xml);Cat cat1 ioc.getBean(cat, Cat.class);Cat cat2 ioc.getBean(cat, Cat.class);Cat cat3 ioc.getBean(cat, Cat.class);System.out.println(cat1 cat1);System.out.println(cat2 cat2);System.out.println(cat3 cat3);
}使用细节 1)bean默认是单例singleton; 在启动容器时, bean默认就会创建, 并放入到singletonObjects 2) 当bean scope“prototype”设置为多实例机制后, 该bean是在getBean()时被创建 3) 如果是单例singleton, 同时希望在getBean时才创建, 可以指定懒加载 lazy-inittrue(注意默认是false) 4) 通常情况下, lazy-init 就使用默认值false. 在开发看来, 空间换时间是值得的, 除非有特殊要求 5) 如果scope“prototype”, 这时你的lazy-init 属性的值不管是true还是false, 都是在getBean的时候才创建这个对象 bean的生命周期 bean对象创建是由JVM完成的, 然后执行如下方法 执行构造器执行set相关方法调用bean的初始化方法(需要配置)使用bean当容器关闭的时候, 调用bean的销毁方法(需要配置) public class House {private String name;public House() {System.out.println(House构造器 被执行...);}public void setName(String name) {System.out.println(House setName() name);this.name name;}//解读//1.这个方法是由程序员来编写的//2.根据自己的业务逻辑来写.//3.名字也不是固定的public void init() {System.out.println(House init()....);}//解读//1.这个方法是由程序员来编写的//2.根据自己的业务逻辑来写.//3.名字也不是固定的public void destroy() {System.out.println(House destroy()...);}
}!--配置House对象, 演示整个bean的生命周期
解读
1.init-methodinit 指定bean的初始化方法, 在setter方法后执行
2.init方法执行的时机, 由spring容器控制
3.destroy-methoddestroy 指定bean的销毁方法, 在容器关闭的时候执行
4.destroy方法执行的时机, 由spring容器控制
--
bean classcom.zzw.spring.bean.House idhouseinit-methodinit destroy-methoddestroyproperty namename value上海豪宅/
/bean测试bean的生命周期 public class SpringBeanTest {Testpublic void testBeanLife() {ApplicationContext ioc new ClassPathXmlApplicationContext(beans.xml);House house ioc.getBean(house, House.class);System.out.println(house house);//关闭容器//1.ioc的编译类型 ApplicationContext, 运行类型 ClassPathXmlApplicationContext//2.因为ClassPathXmlApplicationContext 实现了 ConfigurableApplicationContext//3.ClassPathXmlApplicationContext 是由close()//4.将ioc 转成ClassPathXmlApplicationContext, 再调用close()//ioc.close()//5.关闭ioc容器((ClassPathXmlApplicationContext) ioc).close();}
}输出 House构造器 被执行...
House setName()上海豪宅
House init()....
setMemberDao()...
housecom.zzw.spring.bean.House327bcebd
House destroy()...使用细节 1.初始化init方法和destroy方法, 由程序员来指定 2.销毁方法就是当关闭容器时, 才会被调用 配置bean后置处理器 1在spring的ioc容器, 可以配置bean的后置处理器 2.该 处理器/对象 会在bean初始化方法调用前和初始化方法调用后被调用 3.程序员可以在后置处理器中编写自己的代码 package com.zzw.spring.bean;//ctrlh 可以查看类的继承关系
//这是一个后置处理器, 需要实现 BeanPostProcessor接口
public class MyBeanPostProcessor implements BeanPostProcessor {/*** 什么时候被调用: 在Bean的init方法前被调用* param bean 传入在IOC容器中 创建/配置 的bean* param beanName 传入在IOC容器中 创建/配置 的bean的id* return Object 是程序员对传入的bean进行修改/处理[如果有需要的话], 返回* throws BeansException*/Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println(postProcessBeforeInitialization()... bean bean beanName beanName);return bean;}/*** 什么时候被调用: 在Bean的init方法后被调用* param bean 传入在IOC容器中 创建/配置 的bean* param beanName 传入在IOC容器中 创建/配置 的bean的id* return Object 是程序员对传入的bean进行修改/处理[如果有需要的话], 返回* throws BeansException*/Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println(postProcessAfterInitialization()... bean bean beanName beanName);return bean;}
}新建beans02.xml配置文件 !--配置House对象--
bean classcom.zzw.spring.bean.House idhouseinit-methodinitdestroy-methoddestroyproperty namename value大豪宅/
/bean!--配置后置处理器对象
解读:
1.当我们在beans02.xml 容器配置文件, 配置了MyBeanPostProcessor
2.这时后置处理器对象, 就会作用在该容器的创建的bean对象
--
bean classcom.zzw.spring.bean.MyBeanPostProcessor idbeanPostProcessor/测试 package com.zzw.spring.test;public class SpringBeanTest {Testpublic void testBeanPostProcessor() {ApplicationContext ioc new ClassPathXmlApplicationContext(beans02.xml);House house ioc.getBean(house, House.class);System.out.println(使用house house);//关闭容器//ioc不能调用子类的特有的成员//因为在编译阶段, 能调用哪些成员, 是由编译类型来决定的//ioc编译类型 ApplicationContext, 运行类型 ClassPathXmlApplicationContext((ClassPathXmlApplicationContext) ioc).close();//向下转型}
}其它说明 1.怎么执行到这个方法? 使用AOP(反射动态代理IO容器注解) 2.有什么用? 可以对IOC容器中所有的对象进行统一处理, 比如日志处理/权限校验/安全验证/事务管理. -初步体验案例: 如果类型是House的同意改成 上海豪宅 3.针对容器的所有对象吗? 是的切面编程 4.后面我们会自己实现这个底层机制 5.这是一个比较难以理解的知识点. !--配置House对象--
bean classcom.zzw.spring.bean.House idhouseinit-methodinitdestroy-methoddestroyproperty namename value大豪宅/
/beanbean classcom.zzw.spring.bean.House idhouse02init-methodinitdestroy-methoddestroyproperty namename value宫殿/
/bean!--配置后置处理器对象
解读:
1.当我们在beans02.xml 容器配置文件, 配置了MyBeanPostProcessor
2.这时后置处理器对象, 就会作用在该容器的创建的bean对象
3.已经是针对所有对象编程-切面编程AOP
--
bean classcom.zzw.spring.bean.MyBeanPostProcessor idbeanPostProcessor/public class MyBeanPostProcessor implements BeanPostProcessor {Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println(postProcessBeforeInitialization()... bean bean beanName beanName);//对多个对象进行处理/编程切面编程if (bean instanceof House) {((House) bean).setName(上海豪宅~);}return bean;}Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println(postProcessAfterInitialization()... bean bean beanName beanName);return bean;}
}public class SpringBeanTest {Testpublic void testBeanPostProcessor() {ApplicationContext ioc new ClassPathXmlApplicationContext(beans02.xml);House house ioc.getBean(house, House.class);House house02 ioc.getBean(house02, House.class);System.out.println(使用house house);System.out.println(使用house house02);//关闭容器//ioc不能调用子类的特有的成员//因为在编译阶段, 能调用哪些成员, 是由编译类型来决定的//ioc编译类型 ApplicationContext, 运行类型 ClassPathXmlApplicationContext((ClassPathXmlApplicationContext) ioc).close();//向下转型}
}测试结果 House构造器 被执行...
House setName()大豪宅
postProcessBeforeInitialization()... beanHouse{name大豪宅} beanNamehouse
House setName()上海豪宅~
House init()....
postProcessAfterInitialization()... beanHouse{name上海豪宅~} beanNamehouse
House构造器 被执行...
House setName()宫殿
postProcessBeforeInitialization()... beanHouse{name宫殿} beanNamehouse02
House setName()上海豪宅~
House init()....
postProcessAfterInitialization()... beanHouse{name上海豪宅~} beanNamehouse02
使用houseHouse{name上海豪宅~}
使用houseHouse{name上海豪宅~}
House destroy()...
House destroy()...通过属性文件配置bean 在spring的ioc容器, 通过属性文件给bean注入值 在src目录下, 新建配置文件my.properties [配置文件都要写在src目录下] monsterId1000
name\u5343\u5e74\u9f9f
skill\u65cb\u8f6c\u6253\u51fb解决中文乱码问题 !--指定属性文件
说明
1.先把文件修改成提示All Problem
2.提示错误, 将光标放在context 输入altenter, 就会自动引入namespace
3.locationclasspath:my.properties 表示指定属性文件的位置
4.提示, 需要带上 classpath
--
context:property-placeholder locationclasspath:my.properties/!--配置monster对象
1.通过属性文件给monster对象的属性赋值
2.这时我们的属性值, 通过${属性名}
3.这里说的 属性名, 就是 my.properties文件中的 kv 的k
--
bean classcom.zzw.spring.bean.Monster idmonster100property namemonsterId value${monsterId}/property namename value${name}/property nameskill value${skill}/
/beanpublic class SpringBeanTest {//通过属性文件给bean属性赋值Testpublic void setBeanByFile() {ApplicationContext ioc new ClassPathXmlApplicationContext(beans03.xml);Monster monster100 ioc.getBean(monster100, Monster.class);System.out.println(monster100 monster100);}
}基于XML的bean的自动装配 在spring的ioc容器, 可以实现自动装配bean 这里说的Action就是我们前面学习过的Servlet - 充当Controller Dao package com.zzw.spring.dao;public class OrderDao { //DAO类public void saveOrder() {System.out.println(保存一个订单....);}
}Service package com.zzw.spring.service;public class OrderService { //Service类//OrderDao属性private OrderDao orderDao;//getter方法public OrderDao getOrderDao() {return orderDao;}//setter方法public void setOrderDao(OrderDao orderDao) {this.orderDao orderDao;}
}Action package com.zzw.spring.web;public class OrderAction { //Servlet就是Controller//OrderService属性private OrderService orderService;//getter方法public OrderService getOrderService() {return orderService;}//setter方法public void setOrderService(OrderService orderService) {this.orderService orderService;}
}bean03.xml !--配置OrderDao对象--
bean classcom.zzw.spring.dao.OrderDao idorderDao/
!--配置OrderService对象
解读:
1.autowirebyType 表示 在创建orderService时,通过类型的方式给对象的属性 自动完成赋值/引用
2.比如OrderService对象有 private OrderDao orderDao
3.就会在容器中去找有没有 OrderDao类型对象
4.如果有, 就会自动地装配. 提示: 如果是按照 byType 方式来装配, 这个容器中不能有两个OrderDao类型的对象
5.如果你的对象没有属性, autowire就没有必要写
6.其它类推...
--
bean autowirebyType classcom.zzw.spring.service.OrderServiceidorderService/
!--配置OrderAction对象--
bean autowirebyType classcom.zzw.spring.web.OrderAction idorderAction/通过自动装配来对属性赋值 //通过自动装配来对属性赋值
public class SpringBeanTest {Testpublic void setBeanByAutowire() {ApplicationContext ioc new ClassPathXmlApplicationContext(beans03.xml);OrderAction orderAction ioc.getBean(orderAction, OrderAction.class);//验证是否自动装配上OrderServiceSystem.out.println(orderAction.getOrderService());//验证是否自动装配上OrderDaoSystem.out.println(orderAction.getOrderService().getOrderDao());}
}byName方式讲解 !--
7.如果我们设置的是 autowirebyName 表示通过名字完成自动装配
8.比如下面的 autowirebyName classcom.zzw.spring.service.OrderService1) 先看 OrderService 属性 private OrderDao orderDao;2) 再根据这个属性的setXxx()方法的 xxx 来找对象id3) public void setOrderDao() 就会找 idorderDao对象来进行自动装配4) 如果没有就装配失败
--
bean autowirebyName classcom.zzw.spring.service.OrderServiceidorderService/
!--配置OrderAction对象--
bean autowirebyName classcom.zzw.spring.web.OrderActionidorderAction/Spring El 表达式配置Bean 1.Spring Expression Language, Spring表达式语言, 简称SpEL. 支持运行时查询并可以操作对象. 2.和EL表达式一样, SpEL根据JavaBean风格的getXxx(), setXxx()方法定义的属性访问对象 3.SpEL使用#{…}作为界定符, 所有在大括号中的字符都被认为是SpEL表达式 4.不是重点, 能看懂即可. public class SpELBean {private String name;private Monster monster;private String monsterName;private String crySound;private String bookName;private Double reuslt;public SpELBean() {}//普通方法, 返回字符串public String cry(String crySound) {return 发出 的声音;}//静态方法 返回字符串public static String read(String bookName) {return 正在读 bookName;}//getter方法, setter方法Overridepublic String toString() {return SpELBean{ name name \ \nmonster monster \nmonsterName monsterName \ \ncrySound crySound \ \nbookName bookName \ \nreuslt reuslt };}
}beans04.xml !--配置一个monster对象--
bean classcom.zzw.spring.bean.Monster idmonster01p:monsterId001p:name齐天大圣p:skill金箍棒
/!--spring el 表达式使用
解读
1.通过spEl给bean的属性赋值
--
bean classcom.zzw.spring.bean.SpELBean idspELBean!--sp el 给字面量--property namename value#{赵志伟}/!--sp el 引用其它bean--property namemonster value#{monster01}/!--sp el 引用其它bean的属性值--property namemonsterName value#{monster01.name}/!--sp el 调用普通方法(返回值) 赋值--property namecrySound value#{spELBean.cry(小猫)}/!--sp el 调用静态方法(返回值) 赋值--property namebookName value#{T(com.zzw.spring.bean.SpELBean).read(安乐传)}/!--sp el 通过运算赋值--property namereuslt value#{7253*33.8}/
/bean//通过spring el 对属性赋值
public class SpringBeanTest {Testpublic void setBeanBySpEl() {ApplicationContext ioc new ClassPathXmlApplicationContext(beans04.xml);SpELBean spELBean ioc.getBean(spELBean, SpELBean.class);System.out.println(spELBean spELBean);}
}测试结果 spELBeanSpELBean{name赵志伟
monsterMonster{monsterId1, name齐天大圣, skill金箍棒}
monsterName齐天大圣
crySound发出 小猫 的声音
bookName正在读安乐传
reuslt1863.3999999999999}下乘: Spring系列二基于注解配置bean. 未完待续…