spring5之IOC入门笔记
下一篇-spring代理
目录
- 第一章 spring概述
- 第二章 IOC之XML方式管理bean
- 2.1导入依赖
- 2.2 创建容器
- 2.3 获取Bean对象
- 2.4 bean对象设置别名
- 2.5 bean的依赖注入
- 2.5.1 基于setter方法注入
- 2.5.1.1 注入空值
- 2.5.1.2 注入对象
- 2.5.1.3 注入集合
- 2.5.1.4 注入级联属性
- 2.5.1.5 注入属性
- 2.5.2基于有参构造方法注入
- 2.5.2.1 名称构造注入
- 2.5.2.2 下标构造注入
- 2.5.2.3 类型构造注入
- 2.5.2.4注入空值
- 2.5.2.5 注入对象
- 2.5.2.6 注入集合
- 2.5.3基于p&c名称空间注入
- 2.6 bean的自动注入
- 2.6.1 什么是自动注入
- 2.6.2 自动注入的方式
- 2.7 bean的实例化
- 2.7.1 使用无参构造实例化
- 2.7.2 使用静态工厂方法实例化
- 2.7.3 使用实例工厂类方法实例化
- 2.8 bean的前置实例化
- 2.8.1 什么是bean的前置实例化
- 2.8.2 实例化之间的关系
- 2.9 bean的延迟加载
- 2.9.1 什么是延迟加载
- 2.10 bean的作用域
- 2.11 bean的生命周期
- 2.11.1 什么是bean的生命周期
- 第三章 IOC之注解方式管理Bean
- 3.1 半注解方式管理bean对象
- 3.2 按类型进行自动注入
- 3.3 按名称进行自动注入
- 3.4 注入基本数据类型
- 3.5 注入外部属性文件
- 3.6 bean的作用域
- 3.7 全注解方式管理bean对象
- 3.8 javaconfig 配置方式管理bean
- 3.9 环境切换
- 3.10 通过注解导入外部属性文件
- 3. 11 导入普通对象
- 3.12 导入原生配置文件
第一章 spring概述
spring框架就像是一个容器,有两大特性,IOC与AOP,IOC管理着所有的对象创建与销毁,使开发人员专注于业务的开发,脱离于对象之间的繁杂依赖关系,AOP动态增强,再不改动代码的情况下实现原有业务上功能的增强,通过动态代理实现业务增强,并植入到增强的业务当中。
第二章 IOC之XML方式管理bean
2.1导入依赖
创建一个普通的maven项目
pom.xml
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.2</version>
</dependency>
配置文件 applicationContext.xml(名称可以任意取)
这个配置文件规定了spring的配置方式,context是上下文,如果需要配置aop或者事务,则引入对应的命名规范,如果编写代码,没有对应的提示,请检查是否引入对应的命名规范。
<?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:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><beans>
创建实体对象(也就是bean对象,spring把所有的类统称为bean)
User.java
package com.lyf.iocdemo.entity;/*** @Author: lyf* @CreateTime: 2022-10-11* @description:*/
public class User {//姓名private String name;//性别private Character gender;//年龄private Integer age;//金钱private Double money;//删除private Boolean flag;public User(){}public void setName(String name){this.name = name;}public void setGender(Character gender){this.gender =gender;}public void setAge(Integer age) {this.age = age;}public void setMoney(Double money) {this.money = money;}public void setFlag(Boolean flag) {this.flag = flag;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", gender=" + gender +", age=" + age +", money=" + money +", flag=" + flag +'}';}
}
配置Bean对象
第一种方式
通过class对象 值是bean对象所在的包路径 。
<?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:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><bean class="com.lyf.iocdemo.entity.User"/></beans>
第二种 多了一个id属性,这个id属性在整个容器中是唯一的。
<bean id="user" class="com.lyf.iocdemo.entity.User"/>
第三种 是一个name属性,这个name属性在整个容器中不是唯一的,可以有多个 中间用空格分开。
<bean name="user" class="com.lyf.iocdemo.entity.User"/><bean name="user user1 user2" class="com.lyf.iocdemo.entity.User"/>
2.2 创建容器
容器是用于获取bean对象的,spring通过读取配置文件的内容来创建对象。
添加单元测试到pom中
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency>
第一种创建容器方式 new一个ClassPathXmlApplicationContext对象,通过配置文件所在的类路径加载创建
@Testpublic void createIOCTest(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");}
第二种创建容器方式 通过配置文件所在绝对路径的方式创建容器
@Testpublic void createIOCTest(){ApplicationContext applicationContext = new FileSystemXmlApplicationContext("D:\\eclipse-workspace\\ioc-demo-01\\src\\main\\resources\\applicationContext.xml");}
2.3 获取Bean对象
在测试包文件夹下创建一个IOC测试类,编写测试方法
获取bean实例的方式
@Test//获取bean的三种方式public void getBeanTest(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");//第一种获取方式:通过类名获取User bean1 = (User) applicationContext.getBean(User.class);//第二种:通过bean定义时的id或者name属性获取User bean2 = (User)applicationContext.getBean("user");//第三种,上两种的结合User bean3 = applicationContext.getBean("user", User.class);System.out.println(bean1);System.out.println(bean2);System.out.println(bean3);}
获取bean实例对象结果
2.4 bean对象设置别名
别名有一个单独的标签,name属性的值是bean对象,alias是别名的值,一个别名可以给另一个别名起新别名
<alias name="user" alias="user2"/><bean id="user" class="com.lyf.iocdemo.entity.User"/>
<!-- bean的别名--><alias name="user" alias="user2"/>//第一个别名<alias alias="user" name="user2"/>//第二个别名
2.5 bean的依赖注入
2.5.1 基于setter方法注入
基于setter方法注入:spring容器会通过对象的setter方法完成注入,(也就是说把配置文件中的值通过对象的setter方法赋值)所以基于setter方法注入不能没有setter方法,这里重写了Object类的toString方法,可以让打印对象直接打印值输出,而不是内存地址。
package com.lyf.iocdemo.entity;public class User {//姓名private String name;//性别private Character gender;//年龄private Integer age;//金钱private Double money;//删除private Boolean flag;public void setName(String name){this.name = name;}public String getName(){return name;}public void setGender(Character gender){this.gender =gender;}public Character getGender(){return gender;}public void setAge(Integer age) {this.age = age;}public Integer getAge() {return age;}public void setMoney(Double money) {this.money = money;}public void setFlag(Boolean flag) {this.flag = flag;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", gender=" + gender +", age=" + age +", money=" + money +", flag=" + flag +'}';}
}
配置文件setter方法注入
<bean id="user" class="com.lyf.iocdemo.entity.User"><property name="name" value="张三"/><property name="age" value="10"/><property name="gender" value="男"/><property name="money" value="100"/><property name="flag" value="1"/></bean>
测试案例
@Testpublic void setterTest2(){ApplicationContext applicationContext = new FileSystemXmlApplicationContext("D:\\eclipse-workspace\\ioc-demo-01\\src\\main\\resources\\applicationContext.xml");User user = applicationContext.getBean(User.class);System.out.println("user = " + user);}
运行结果
2.5.1.1 注入空值
<bean id="user" class="com.lyf.iocdemo.entity.User"><property name="name" value="#{null}"/></bean>
测试案例
@Testpublic void nullTest(){//第一中获取bean的方式ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");User user = applicationContext.getBean(User.class);System.out.println("user.name = " + user.getName());
运行结果
2.5.1.2 注入对象
创建一个Department类与Employee类,在雇员类中注入部门属性,这个部门 属性需要有getter方法
Department类
public class Department {private String name;public Department(){}public Department(String name){this.name = name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Department{" +"name='" + name + '\'' +'}';}
}
Employye类
public class Employee {private String name;private String age;private Department dep;public Employee(){}public Employee(String name,String age,Department dep){this.name = name;this.age =age;this.dep =dep;}public void setName(String name) {this.name = name;}public void setDep(Department dep) {this.dep = dep;}public void setAge(String age) {this.age = age;}public Department getDep() {return dep;}@Overridepublic String toString() {return "Department{" +"name='" + name + '\'' +", age='" + age + '\'' +", dep=" + dep +'}';}
}
xml配置文件 ref =“def” 属于引用dep这个别名的bean
<bean id="department" class="com.lyf.iocdemo.entity.Department"><property name="name" value="财务部"/></bean><alias name="department" alias="dep"/><bean id="emp" class="com.lyf.iocdemo.entity.Employee"><property name="name" value="王二"/><property name="age" value="10"/><property name="dep" ref="dep"/></bean>
运行结果
2.5.1.3 注入集合
集合中注入的值为基本数据类型
public class CollectionBean {//数组类型private String[] strings;//集合类型private List list;private Map map;private Set<String> set;public void setList(List list) {this.list = list;}public void setMap(Map map) {this.map = map;}public void setSet(Set<String> set) {this.set = set;}public void setStrings(String[] strings) {this.strings = strings;}@Overridepublic String toString() {return "CollectionBean{" +"strings=" + Arrays.toString(strings) +", list=" + list +", map=" + map +", set=" + set +'}';}
xml配置文件 集合中是基本数据类型的话,直接注入值就行,根据集合类型选择对应的标签。
<bean id="collection" class="com.lyf.iocdemo.entity.CollectionBean">
<!-- 数组类型--><property name="strings"><array><value>王</value><value>李</value><value>赵</value><value>梁</value></array></property><property name="list"><list><value>lao</value><value>peng</value><value>yu</value><value>qin</value></list></property><property name="set"><set><value>very</value><value>much</value><value>love</value></set></property><property name="map"><map><entry key="p" value="peng"/><entry key="y" value="yu"/><entry key="q" value="qin"/></map></property></bean>
运行结果
集合中注入的值为对象类型
package com.lyf.iocdemo.entity;import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;/*** @Author: lyf* @CreateTime: 2022-10-11* @description:*/
public class CollectionObjectBean {private Employee[] employees;private List<Employee> employeeList;private Set<Employee> employeeSet;private Map<String,Employee> employeeMap;public void setEmployeeList(List<Employee> employeeList) {this.employeeList = employeeList;}public void setEmployeeSet(Set<Employee> employeeSet) {this.employeeSet = employeeSet;}public void setEmployeeMap(Map<String, Employee> employeeMap) {this.employeeMap = employeeMap;}public void setEmployees(Employee[] employees) {this.employees = employees;}@Overridepublic String toString() {return "CollectionObjectBean{" +"employees=" + Arrays.toString(employees) +", employeeList=" + employeeList +", employeeSet=" + employeeSet +", employeeMap=" + employeeMap +'}';}
}
xml 配置 注入的对象直接使用 <ref 标签引用即可。
<!--注入对象集合属性--><bean name="objectBean" class="com.lyf.iocdemo.entity.CollectionObjectBean"><property name="employees"><array><ref bean="emp"/><ref bean="emp1"/><ref bean="em2"/></array></property><property name="employeeList"><list><ref bean="emp"/><ref bean="emp1"/><ref bean="em2"/></list></property><property name="employeeSet"><set><ref bean="emp"/><ref bean="emp1"/><ref bean="em2"/></set></property><property name="employeeMap"><map><entry key="1" value-ref="emp"/><entry key="2" value-ref="emp1"/><entry key="3" value-ref="em2"/></map></property></bean>
运行结果
2.5.1.4 注入级联属性
级联属性表示,一个类中有一个属性是另一个类。
package com.lyf.iocdemo.entity;public class Flower {/*** 花的名称*/private String name;/*** 花的颜色*/private Color color;public void setName(String name) {this.name = name;}public void setColor(Color color) {this.color = color;}@Overridepublic String toString() {return "Flower{" +"name='" + name + '\'' +", color=" + color +'}';}
}
package com.lyf.iocdemo.entity;public class Color {/*** 颜色名称*/private String red;/*** 绿色*/private String greed;/*** 黑色*/private String black;public void setRed(String red) {this.red = red;}public void setGreed(String greed) {this.greed = greed;}@Overridepublic String toString() {return "Color{" +"red='" + red + '\'' +", greed='" + greed + '\'' +", black='" + black + '\'' +'}';}public void setBlack(String black) {this.black = black;}
}
<bean id="flower" class="com.lyf.iocdemo.entity.Flower"><property name="name" value="flower"></property><property name="color"><bean class="com.lyf.iocdemo.entity.Color"><property name="black" value="黑色"/><property name="greed" value="绿色"/><property name="red" value="红色"/></bean></property></bean>
运行结果
2.5.1.5 注入属性
package com.lyf.iocdemo.entity;import java.util.Properties;/*** @Author: lyf* @CreateTime: 2022-10-11* @description:*/
public class PropertiesBean {private Properties properties;public void setProperties(Properties properties) {this.properties = properties;}@Overridepublic String toString() {return "Properties{" +"properties=" + properties +'}';}
}
<!-- 注入属性信息--><bean name="properties" class="com.lyf.iocdemo.entity.PropertiesBean"><property name="properties"><props><prop key="username">password</prop><prop key="password">admin</prop></props></property></bean>
运行结果
注入外部属性
创建properties.properties文件 ,写入一下值
user.username=username
user.password=password`
<!-- 加载外部文件--><context:property-placeholder location="classpath:properties.properties" local-override="true"/><bean id="propertiesBean" class="com.lyf.iocdemo.entity.PropertiesBean"><property name="properties"><props><prop key="username">${user.username}</prop><prop key="password">${user.password}</prop></props></property></bean>````提示:这里简述项目相关背景:`Description:Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.Reason: Failed to determine a suitable driver class---# 问题描述
`提示:这里描述项目中遇到的问题:`例如:数据传输过程中数据不时出现丢失的情况,偶尔会丢失一部分数据
APP 中接收数据代码:```c
@Overridepublic void run() {bytes = mmInStream.read(buffer);mHandler.obtainMessage(READ_DATA, bytes, -1, buffer).sendToTarget();}
2.5.2基于有参构造方法注入
2.5.2.1 名称构造注入
修改User类,把属性值全部通过构造函数赋值。spring容器会调用有参构造方法把配置文件中的值赋值给bean。
package com.lyf.iocdemo.entity;public class User {//姓名private String name;//性别private Character gender;//年龄private Integer age;//金钱private Double money;//删除private Boolean flag;public User(){}public User(String name,Character gender,Integer age,Double money,Boolean flag){this.name = name;this.gender = gender;this.age = age;this.money =money;this.flag =flag;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", gender=" + gender +", age=" + age +", money=" + money +", flag=" + flag +'}';}
}
constructor-arg单词表示构造-参数,这里可以在新建一个配置文件或者保证bean的id或者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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 基于有参构造注入-->
<!--基于名称--><bean id="user1" class="com.lyf.iocdemo.entity.User"><constructor-arg name="name" value="peng"/><constructor-arg name="gender" value="女"/><constructor-arg name="age" value="22"/><constructor-arg name="money" value="200"/><constructor-arg name="flag" value="true"/></bean></beans>
测试代码
@Testpublic void constrNameTest(){ApplicationContext context = new ClassPathXmlApplicationContext("context.xml");Object user1 = (User)context.getBean("user1");System.out.println(user1);}
运行结果
2.5.2.2 下标构造注入
User类不变,index下标 表示构造函数中参数个数的下标位置,下标中的值对应着参数的位置,value属性的值都要用引号,spring会根据参数类型赋值。
<!--基于下标--><bean name="user2" class="com.lyf.iocdemo.entity.User"><constructor-arg index="0" value="liang"/><constructor-arg index="1" value="女"/><constructor-arg index="2" value="18"/><constructor-arg index="3" value="1000"/><constructor-arg index="4" value="1"/></bean>
2.5.2.3 类型构造注入
type的值必须是包装类数据类型。不能是基本数据类型,比如 int double类型等。
<!--基于数据类型--><bean name="user3" class="com.lyf.iocdemo.entity.User"><constructor-arg type="java.lang.String" value="yu"/><constructor-arg type="java.lang.Character" value="男"/><constructor-arg type="java.lang.Integer" value="12"/><constructor-arg type="java.lang.Double" value="232"/><constructor-arg type="java.lang.Boolean" value="true"/></bean>
2.5.2.4注入空值
修改User类,加入一个name属性的有参构造。使用有参构造注入,参数类型必须赋值。比如, 一个有参构造函数有4个参数,但却赋值一个是不行的,必须全部赋值,如果只想单独赋值给一个属性,则创建对应的有参构造函数。
public User(String name){this.name = name;}
<!-- 注入空值--><bean name="user" class="com.lyf.iocdemo.entity.User"><constructor-arg name="name" value="#{null}"/></bean>
2.5.2.5 注入对象
由于是有参构造,Employee 类不需要使用使用Department 的getter方法获取department值。spring直接传引用地址进行赋值。
package com.lyf.iocdemo.entity;public class Employee {private String name;private String age;private Department dep;public Employee(){}public Employee(String name,String age,Department dep){this.name = name;this.age =age;this.dep =dep;}@Overridepublic String toString() {return "Department{" +"name='" + name + '\'' +", age='" + age + '\'' +", dep=" + dep +'}';}
}
package com.lyf.iocdemo.entity;public class Department {private String name;public Department(){}public Department(String name){this.name = name;}@Overridepublic String toString() {return "Department{" +"name='" + name + '\'' +'}';}
}
<!-- 注入对象类型--><bean name="dep" class="com.lyf.iocdemo.entity.Department"><constructor-arg name="name" value="设计部"/></bean><bean id="emp1" class="com.lyf.iocdemo.entity.Employee"><constructor-arg name="name" value="hua"/><constructor-arg index="1" value="23"/><constructor-arg type="com.lyf.iocdemo.entity.Department" ref="dep"/></bean>
第二种方式注入对象
与第一种方式不同的是,第二种可以选择对应的类型来赋值,比如,选择名称属性,或者数据类型属性,index下标属性等;在赋值其他bean时,可以选择ref引用,也可以在该标签下创建bean对象进行赋值。
<!-- 第二种方式--><bean name="emp2" class="com.lyf.iocdemo.entity.Employee"><constructor-arg name="name" value="pengyuqin"/><constructor-arg type="java.lang.String" value="12"/><constructor-arg name="dep"><bean id="dep1" class="com.lyf.iocdemo.entity.Department"><constructor-arg index="0" value="维修部"/></bean></constructor-arg></bean>
2.5.2.6 注入集合
注入集合 值是基本数据类型
package com.lyf.iocdemo.entity;import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;public class CollectionBean {//数组类型private String[] strings;//集合类型private List list;private Map map;private Set<String> set;public CollectionBean(String[] strings, List list, Map map, Set<String> set) {this.strings = strings;this.list = list;this.map = map;this.set = set;}@Overridepublic String toString() {return "CollectionBean{" +"strings=" + Arrays.toString(strings) +", list=" + list +", map=" + map +", set=" + set +'}';}
}
有参构造的属性可以任意选择,index下标,name属性,type类型都可以。
<!-- 注入集合--><bean name="collectionBean" class="com.lyf.iocdemo.entity.CollectionBean"><constructor-arg name="strings"><array><value>王一</value><value>王二</value><value>王三</value><value>王四</value></array></constructor-arg><constructor-arg type="java.util.List"><list><value>李一</value><value>李二</value><value>李三</value><value>李四</value><value>李五</value></list></constructor-arg><constructor-arg index="3"><set><value>赵一</value><value>赵二</value><value>赵三</value><value>赵四</value><value>赵五</value></set></constructor-arg><constructor-arg name="map"><map><entry key="1" value="吴一"/><entry key="2" value="吴二"/><entry key="3" value="吴三"/><entry key="4" value="吴四"/><entry key="5" value="吴五"/></map></constructor-arg></bean>
测试代码
@Testpublic void collectionBean(){CollectionBean collectionBean = (CollectionBean)new ClassPathXmlApplicationContext("context.xml").getBean("collectionBean");System.out.println(collectionBean);}
运行结果
注入集合,值是对象类型
package com.lyf.iocdemo.entity;import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;public class CollectionObjectBean {private Employee[] employees;private List<Employee> employeeList;private Set<Employee> employeeSet;private Map<String,Employee> employeeMap;public CollectionObjectBean(Employee[] employees, List<Employee> employeeList, Set<Employee> employeeSet, Map<String, Employee> employeeMap) {this.employees = employees;this.employeeList = employeeList;this.employeeSet = employeeSet;this.employeeMap = employeeMap;}@Overridepublic String toString() {return "CollectionObjectBean{" +"employees=" + Arrays.toString(employees) +", employeeList=" + employeeList +", employeeSet=" + employeeSet +", employeeMap=" + employeeMap +'}';}
}
<!-- 注入集合 值是对象类型--><bean name="collectionObject" class="com.lyf.iocdemo.entity.CollectionObjectBean"><constructor-arg name="employees"><array><ref bean="emp1"/><ref bean="emp1"/><ref bean="emp1"/><ref bean="emp1"/></array></constructor-arg><constructor-arg type="java.util.List"><list><ref bean="emp1"/><ref bean="emp1"/><ref bean="emp1"/><ref bean="emp1"/><ref bean="emp1"/></list></constructor-arg><constructor-arg index="2"><set><ref bean="emp2"/><ref bean="emp1"/><ref bean="emp1"/><ref bean="emp1"/><ref bean="emp1"/></set></constructor-arg><constructor-arg name="employeeMap"><map><entry key="1" value-ref="emp2"/><entry key="2" value-ref="emp2"/><entry key="3" value-ref="emp2"/><entry key="4" value-ref="emp2"/><entry key="5" value-ref="emp2"/></map></constructor-arg></bean>
2.5.3基于p&c名称空间注入
加入p&c命名空间的规范
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
User类对象
package com.lyf.iocdemo.entity;public class User {//姓名private String name;//性别private Character gender;//年龄private Integer age;//金钱private Double money;//删除private Boolean flag;public User(){}public User(String name){this.name = name;}public User(String name,Character gender,Integer age,Double money,Boolean flag){this.name = name;this.gender = gender;this.age = age;this.money =money;this.flag =flag;}public void setName(String name){this.name = name;}public String getName(){return name;}public void setGender(Character gender){this.gender =gender;}public Character getGender(){return gender;}public void setAge(Integer age) {this.age = age;}public Integer getAge() {return age;}public void setMoney(Double money) {this.money = money;}public void setFlag(Boolean flag) {this.flag = flag;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", gender=" + gender +", age=" + age +", money=" + money +", flag=" + flag +'}';}
}
p&c名称空间注入 ,相对于简写property与constructor-arg属性,属性p&c必须是在bean的单标签当中。
注入基本数据类型
<?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"xmlns:c="http://www.springframework.org/schema/c"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 基于p名称空间的注入--><bean id="user3" class="com.lyf.iocdemo.entity.User"p:name="pengyuqin"p:age="23"p:gender="女"p:money="112"p:flag="false"/><!-- 基于c名称空间的注入--><bean id="user4" class="com.lyf.iocdemo.entity.User"c:name="pengyuqin"c:age="23"c:gender="女"c:money="112"c:flag="false"/></beans>
p&c注入对象类型
需要把Department&Employee的stter方法加上
<!-- 基于p命名空间注入对象--><bean id="department" class="com.lyf.iocdemo.entity.Department"p:name="财务部"/><bean id="employee" class="com.lyf.iocdemo.entity.Employee"p:name="网二"p:age="18"p:dep-ref="department"/>
<!-- 基于c命名空间注入对象--><bean id="department1" class="com.lyf.iocdemo.entity.Department"c:name="财务部"/><bean id="employee1" class="com.lyf.iocdemo.entity.Employee"c:name="网二"c:age="18"c:dep-ref="department"/>
2.6 bean的自动注入
2.6.1 什么是自动注入
表示为我们只需要创建好bean对象,spring容器会帮我们进行依赖管理并注入对象,比如
我们创建好Department这个bean对象,在Employee这个bean中需要Department对象,我们可以不用赋值,spring会在ioc容器当中找到这个Department(bean)对象,并赋值到Employee的属性当中。
2.6.2 自动注入的方式
方式 | 说明 |
---|---|
no | 默认值,表示不开启自动注入 |
byName | 通过名称进行自动注入,查找bean的id&name属性值进行注入。 |
byType | 通过类型进行自动注入,查找的是class对象所在的类路径全名称。 |
开启自动注入
在beans标签当中加入该属性值
<beans default-lazy-init="true"></beans>
通过autowire
属性开启自动注入
<?xml version="1.0" encoding="UTF-8"?>
<beans default-lazy-init="true" xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean name="dep" class="com.lyf.iocdemo.entity.Department"><property name="name" value="test"/>
</bean><!-- 自动注入-->
<!-- 根据名称自动注入--><bean id="emp" class="com.lyf.iocdemo.entity.Employee" autowire="byName"/>
<!-- 根据类型自动注入--><bean name="emp1" class="com.lyf.iocdemo.entity.Employee" autowire="byType"/></beans>
测试结果
2.7 bean的实例化
2.7.1 使用无参构造实例化
public class Admin {public Admin(){System.out.println("使用无参构造函数实例化Bean");}
}
<!-- 使用无参构造注入--><bean id="admin1" class="com.lyf.iocdemo.entity.Admin"/>
运行结果
2.7.2 使用静态工厂方法实例化
public class Admin {public Admin(){System.out.println("使用静态工厂方法函数实例化Bean");}private static final Admin admin = new Admin();public static Admin createInstance(){return admin;}
}
factory-method的属性值是Admin中的静态方法createInstance
<!-- 使用静态工厂实例对象--><bean id="admin" class="com.lyf.iocdemo.entity.Admin" factory-method="createInstance"/>
运行结果
2.7.3 使用实例工厂类方法实例化
通过AdminFactory类方法实例化
public class AdminFactory {private static Admin admin = new Admin();public static Admin createInstance(){return admin;}
}
admin2去引用adminFactory的实例方法完成bean实例化。
<bean id="adminFactory" class="com.lyf.iocdemo.entity.AdminFactory"/><bean id="admin2" factory-bean="adminFactory" factory-method="createInstance"/>
运行结果
2.8 bean的前置实例化
2.8.1 什么是bean的前置实例化
前置实例化:当一个bean对象是另一个bean对象的属性时,需要用到前置bean实例化,
这种依赖关系,就需要用到bean的实例化。举例:先有鸡还是先有蛋问题,如果我们要控制这种依赖关系,我们就在bean标签当中使用depends-on
属性来控制先有鸡还是先有蛋问题。
Chicken类
public class Chicken {public Chicken(){System.out.println("我是鸡,先有鸡");}
}
public class Eggs {public Eggs(){System.out.println("我是鸡蛋,先有鸡蛋");}
}
<!-- 假设 先有鸡后有蛋,所以我们使鸡蛋的bean对象依赖于Chickenbean对象,则chicken bean在eggs先被实例化 --><bean name="chicken" class="com.lyf.iocdemo.entity.Chicken"/><bean id="eggs" class="com.lyf.iocdemo.entity.Eggs" depends-on="chicken"/>
2.8.2 实例化之间的关系
bean创建过程:
先有 Chicken——>eggs…
bean销毁过程
eggs——>Chicken…
如果有多个依赖关系,则在depends-on
属性上用空格或者逗号或者分号分隔依赖关系。
<!-- 鸡蛋崽崽依赖鸡粑粑与鸡妈妈--><bean name="girlChicken" class="com.lyf.iocdemo.entity.Chicken"/><bean name="boyChicken" class="com.lyf.iocdemo.entity.Chicken"/><bean id="childEggs" class="com.lyf.iocdemo.entity.Eggs" depends-on="girlChicken,boyChicken"/>
2.9 bean的延迟加载
2.9.1 什么是延迟加载
延迟加载对bean对象,在容器创建成功之后,并不会立即实例化这个bean对象,而是等有引用对象需要该对象时,才会加载(实例化对象)该对象。延迟加载也叫按需加载。
<!-- lazy-init 开启懒加载--><bean class="com.lyf.iocdemo.entity.Chicken" lazy-init="true"/>
2.10 bean的作用域
作用域 | 描述 |
---|---|
singleton | 单例模式,表示在容器中,只存在一个bean对象,无论什么样的请求都返回该bean对象给调用者 |
prototype | 多例模式,表示在容器中,只要有请求到该bean对象,spring容器都会创建一个新的bean对象返回。 |
request | 将bean对象的作用域限定在http请求的Request当中。 |
session | 将bean对象的作用域限定在http请求的session当中。 |
application | 将该bean对象的作用域限定在整个http的serveltContext当中 |
websocket | 将该bean对象的作用域限定在整个http的websocket当中 |
开启作用域
<!-- 开启作用域--><bean name="chicken3 chicken4" class="com.lyf.iocdemo.entity.Chicken" scope="singleton"/>
测试代码
@Testpublic void scope(){ApplicationContext context = new ClassPathXmlApplicationContext("ByNameAndByType.xml");Chicken chicken3 = (Chicken)context.getBean("chicken3");Chicken chicken4 = (Chicken)context.getBean("chicken4");System.out.println(chicken3);System.out.println(chicken4);System.out.println(chicken3.equals(chicken4));}
运行结果
多例模式
<!-- 多例模式--><bean name="chicken5 chicken6" class="com.lyf.iocdemo.entity.Chicken" scope="prototype"/>
测试代码
@Test
public void scopePrototype(){ApplicationContext context = new ClassPathXmlApplicationContext("ByNameAndByType.xml");Chicken chicken5 = (Chicken)context.getBean("chicken5");Chicken chicken6 = (Chicken)context.getBean("chicken6");System.out.println(chicken5);System.out.println(chicken6);System.out.println(chicken5.equals(chicken6));
}
运行结果
2.11 bean的生命周期
2.11.1 什么是bean的生命周期
bean对象从创建到销毁的过程。
public class LifeCycle {private String name;public LifeCycle(){System.out.println("执行无参构造");}public LifeCycle(String name){this.name = name;System.out.println("执行有参构造");}public void init(){System.out.println("执行初始化");}public void setName(String name) {this.name = name;System.out.println("执行赋值方法");}public void destroy(){System.out.println("执行销毁方法");}
}
<!-- bean的生命周期--><bean id="lifeCycle" class="com.lyf.iocdemo.entity.LifeCycle"init-method="init" destroy-method="destroy">
<!-- <constructor-arg name="name" value="admin"/>--><property name="name" value="user"/></bean>
测试代码
@Testpublic void lifeCycle(){LifeCycle lifeCycle = (LifeCycle) new ClassPathXmlApplicationContext("ByNameAndByType.xml").getBean("lifeCycle");System.out.println(lifeCycle);lifeCycle.destroy();}
测试结果
如果对象有有参构造则先执行有参构造,如果没有,则默认执行无参构造,如果有有参构造,想先执行无参构造,则声明无参构造即可。
特殊的生命周期BeanPostProcessor
BeanPostProcessor
接口我们也叫后置处理器,作用是在Bean对象在实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑。注意是Bean实例化完毕后及依赖注入完成之后才执行的。
public class MyBeanProcessor implements BeanPostProcessor {/*** 初始化之后执行方法* @param bean* @param beanName* @return* @throws BeansException*/@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {LifeCycle lifeCycle = (LifeCycle)bean;System.out.println("postProcessAfter");lifeCycle.destroy();return lifeCycle;}/*** 初始化之前执行方法* @param bean* @param beanName* @return* @throws BeansException*/@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {LifeCycle lifeCycle = (LifeCycle)bean;System.out.println("postProcessBefore");lifeCycle.init();return lifeCycle;}
}
<!-- 特殊的bean生命周期--><bean name="lifeCycle1" class="com.lyf.iocdemo.entity.LifeCycle"><property name="name" value="roker"/></bean><bean class="com.lyf.iocdemo.entity.MyBeanProcessor"></bean>
测试代码
@Testpublic void lifeCycle(){LifeCycle lifeCycle = (LifeCycle) new ClassPathXmlApplicationContext("ByNameAndByType.xml").getBean("lifeCycle1");System.out.println(lifeCycle);lifeCycle.destroy();}
运行结果
第三章 IOC之注解方式管理Bean
3.1 半注解方式管理bean对象
创建一个新的maven项目,导入依赖
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.1.10.RELEASE</version></dependency>
创建一个bean对象
@Component
:Component译为组件,用于标记这个类是spring容器管理的类,spring容器扫描到这个注解的时候,就会把这个类放入到容器中。spring对Component组件进行了子划分,用于区别不同的模块。表示的功能完全是一样的。
@Repository
: 属于Component组件的子组件(衍生组件)用于表示在数据访问层,dao层。
@Service
:属于Component组件的子组件(衍生组件)用于表示在业务层,service层。
@Controller
: 属于Component组件的子组件(衍生组件)用于表示在控制层,controller层。
如果组件属性没有任何值,则表示当前的类名或方法名的首字母小写形式为该组件的名称
Student类
@Component
//@Repository
//@Service
//@Controllerpublic class Student {private String name;private Integer age;public Student() {}public Student(String name, Integer age) {this.name = name;this.age = age;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';}
}
开启组件扫描
配置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"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!--开启组件扫描--><context:component-scan base-package="com.lyf.spring5"/>
</beans>
注解配置文件,include-filter表示把扫描的注解包含进来,exclude-filter表示排除该注解类型,扫描到该注解则不添加的容器当中。
<!--开启组件扫描--><context:component-scan base-package="com.lyf.spring5"><context:include-filter type="annotation" expression="org.springframework.stereotype.Component"/><context:exclude-filter type="annotation" expression="org.springframework.stereotype.Indexed"/></context:component-scan>
创建StudentDao类
@Repository //表示标记当前类为一个spring组件,并加入到容器当中
public class StudentDao {public Student getStudent(){Student student = new Student("王二明",12);return student;}
}
@Autowired 注入到属性当中
创建StudentService类
@Service //标记当前类为组件(Service类型组件)并加入到spring容器当中
public class StudentService {@Autowired //自动注入注解 表示把StudentDao这个bean注入当前属性当中,这里spring容器管理帮我们创建了studentDao对象private StudentDao studentDao;/*** 调用studentDao的getStudent方法 返回一个student对象* @return*/public Student getStudent(){return studentDao.getStudent();}}
测试代码
public class IocXmlTest {/*** 测试*/@Testpublic void xmlTest(){Student student = new ClassPathXmlApplicationContext("context.xml").getBean(StudentService.class).getStudent();System.out.println(student);}
}
测试结果
3.2 按类型进行自动注入
1.注入到setter方法当中
@Autowiredpublic void setStudentDao(StudentDao studentDao){this.studentDao = studentDao;}
2.注入到私有属性
@Autowired //自动注入注解 表示把StudentDao这个bean注入当前属性当中,这里spring容器管理帮我们创建了studentDao对象private StudentDao studentDao;
3.注入当构造方法
@Autowiredpublic StudentService(StudentDao studentDao){this.studentDao = studentDao;}
3.3 按名称进行自动注入
1.注入到私有属性
@Qualifier("studentDao")
使用该注解表示使用名称进行注入,如果一个接口有多个实现类,则需要使用该注解进行指明需要使用哪个实现类,如果不指明需要实例化哪个实现类,spring容器会默认选择一个类来实例。
@Qualifier
注解必须跟@Autowired
一起使用。
@Qualifier
注解的值是bean的名称,默认是类名的小写形式注入,如果需要修改,则在@Service
注解当中指明bean的名称。
@Autowired//自动注入注解 表示把StudentDao这个bean注入当前属性当中,这里spring容器管理帮我们创建了studentDao对象@Qualifier("studentDao")private StudentDao studentDao;
2.注入到set方法当中
@Autowired@Qualifier("studentDao")public void setStudentDao(StudentDao studentDao){this.studentDao = studentDao;}
3 注入到有参构造函数当中
@Autowiredpublic StudentService(@Qualifier("studentDao") StudentDao studentDao){this.studentDao = studentDao;}
3.4 注入基本数据类型
三种基本类型注入方式
// 第一种属性注入方式@Value("user")private String name;/*** 第二种有参构造注入方式* @param name*/public StudentService(@Value("user1") String name){}/*** 第三种setter方法注入* @param name*/public void setName(@Value("user2") String name) {this.name = name;}
3.5 注入外部属性文件
外部文件admin.properties
user.username =admin
user.password =admin
在配置文件引入外部属性文件。
<!--引入外部文件--><context:property-placeholder location="classpath:admin.properties"/>
//第一种注入外部文件属性方式@Value("${user.username}")private String username;@Value("${user.password}")private String password;/*** 第二种有参构造函数注入方式* @param username* @param password*/public StudentService(@Value("${user.username}") String username,@Value("${user.password}")String password){this.username =username;this.password = password;}/*** 第三种setter方法注入方式* @param username*/public void setUsername(@Value("${user.username}") String username) {this.username = username;}public void setPassword(@Value("${user.password}") String password) {this.password = password;}@Overridepublic String toString() {return "StudentService{" +", username='" + username + '\'' +", password='" + password + '\'' +'}';}
测试代码
@Testpublic void test(){StudentService studentService = new ClassPathXmlApplicationContext("context.xml").getBean(StudentService.class);System.out.println(studentService);}
测试结果
3.6 bean的作用域
单例模式
@Component
@Scope("singleton")
public class Student{}
多例模式
@Component
@Scope("prototype")
public class Student{}
3.7 全注解方式管理bean对象
导入依赖
<!-- spring容器--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.1.10.RELEASE</version></dependency>
<!-- 单元测试--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency>
声明组件
@Component
public class Student{
private String name;
private Integer age;
}
配置文件 相对于xml形式的配置文件。
@Configuration
表示当前类是一个配置文件类
@ComponentScan
表示组件扫描注解,value属性表示扫描的包路径,如果有多个路径需要扫描,则{}
分隔包名。
@Configuration
@ComponentScan(value = "com.lyf.spring5",includeFilters = {@ComponentScan.Filter(classes = Component.class)},excludeFilters = {@ComponentScan.Filter(classes = Controller.class)})
public class AppConfig {
}
默认使用这种模式即可
@Configuration
@ComponentScan("com.lyf.spring5")
public class AppConfig{}
测试代码
@Testpublic void annotationTest(){Object student = new AnnotationConfigApplicationContext(AppConfig.class).getBean("student");System.out.println(student);}
运行结果
3.8 javaconfig 配置方式管理bean
@Configuration
注解表示该类是一个配置,被该注解标记的类都是配置类,与XML的<beans></beans>
相似。
@Bean
注解表示该方法是一个bean对象,被该注解标记的方法是一个bean对象,与XML的<bean></bean>
相似。
@Bean
如果没有属性值,则标记的方法为bean对象的名称默认为方法名。
通常,@Configruation
&@Bean
注解一起使用表示该类是一个配置类
@Configuration
public class JavaConfig {@Beanpublic Student student(){return new Student();}
}
JavaConfig类表示的结果跟xml表示的结果一致。
<beans><bean id="emp" class="com.lyf.iocdemo.entity.Employee"></bean>
</beans>
我们需要注意的是 proxyBeanMethods 属性:
@Configuration(proxyBeanMethods = true)
:代表Full模式,外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象
@Configuration(proxyBeanMethods = false)
:代表Lite模式,外部无论对配置类中的这个组件注册方法调用多少次获取的都是创建一个新的实例对象
3.9 环境切换
创建一个数据源对象
public class DataSource {private String driver;private String url;private String username;private String password;public void setDriver(String driver) {this.driver = driver;}public void setUrl(String url) {this.url = url;}public void setUsername(String username) {this.username = username;}public void setPassword(String password) {this.password = password;}@Overridepublic String toString() {return "DataSource{" +"driver='" + driver + '\'' +", url='" + url + '\'' +", username='" + username + '\'' +", password='" + password + '\'' +'}';}
}
配置多数据源对象类
@Profile({"dev","default"})
该注解表示如果spring容器指定的环境值需要这个bean对象,就会创建并使用。如果没有指定,默认创建该bean对象。
@Configuration
public class DataSourceConfig {@Bean("datasource")@Profile({"dev","default"})public DataSource getDataSourceDevelopment(){DataSource dataSource = new DataSource();dataSource.setDriver("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql://localhost:3306/dev");dataSource.setUsername("root");dataSource.setPassword("root");return dataSource;}@Bean("datasource")@Profile("pro")public DataSource getDataSourceProduction(){DataSource dataSource = new DataSource();dataSource.setDriver("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql://localhost:3306/pro");dataSource.setUsername("root");dataSource.setPassword("root");return dataSource;}
}
测试代码
@Testpublic void test(){//创建spring上下文对象(容器)AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();//通过容器获取环境,并设置激活的配置文件context.getEnvironment().setActiveProfiles("dev");//注册配置文件到上下文当中,context.register(DataSourceConfig.class);//刷新上下文context.refresh();//获取数据库bean对象DataSource bean = context.getBean(DataSource.class);//打印数据库对象的值System.out.println(bean);}
运行结果
3.10 通过注解导入外部属性文件
外部属性文件 jdbc.properties
#开发环境数据库配置
jdbc.dev.driverClass=com.mysql.cj.jdbc.Driver
jdbc.dev.url=jdbc:mysql://localhost:3306/dev
jdbc.dev.username=root
jdbc.dev.password=root#生产环境数据库配置
jdbc.pro.driverClass=com.mysql.jdbc.Driver
jdbc.pro.url=jdbc:mysql://localhost:3306/pro
jdbc.pro.username=root
jdbc.pro.password=456789
配置类 @PropertySource
表示导入一个外部文件,属性值是一个文件的类路径。这里注入了一个Environment 对象,该对象可以获取到外部文件的属性值
package com.lyf.spring5.jdbc;import com.lyf.spring5.ioc.entity.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;
import org.springframework.core.env.Environment;@Configuration
@PropertySource("classpath:jdbc/jdbc.properties")
public class JdbcConfig {@Autowiredprivate Environment env;// 第一种方式获取外部属性文件 。通过Environment 对象获取@Bean@Profile({"dev","default"})public DataSource DevDataSource(){DataSource dataSource = new DataSource();dataSource.setDriver(env.getProperty("jdbc.dev.driverClass"));dataSource.setUrl(env.getProperty("jdbc.dev.url"));dataSource.setUsername(env.getProperty("jdbc.dev.username"));dataSource.setPassword(env.getProperty("jdbc.dev.password"));return dataSource;}// 第二种获取方式,通过@Value注解获取@Value("${jdbc.pro.driver}")private String driver;@Value("${jdbc.pro.url}")private String url;@Value("${jdbc.pro.username}")private String username;@Value("${jdbc.pro.password}")private String password;@Bean@Profile("pro")public DataSource ProDataSource(){DataSource dataSource = new DataSource();dataSource.setDriver(driver);dataSource.setUrl(url);dataSource.setUsername(username);dataSource.setPassword(password);return dataSource;}
}
测试代码
@Testpublic void test(){//创建spring上下文对象(容器)AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();//通过容器获取环境,并设置激活的配置文件context.getEnvironment().setActiveProfiles("dev");//注册配置文件到上下文当中,context.register(JdbcConfig.class);//刷新上下文context.refresh();//获取数据库bean对象DataSource bean = context.getBean(DataSource.class);//打印数据库对象的值System.out.println(bean);}
运行结果
3. 11 导入普通对象
@Import
通过该注解获取普通对象,属性值是一个类。
@Configuration
@Import(Student.class) //导入普通对象
public class JavaConfig {
}
测试代码
@Testpublic void test1(){//创建spring上下文对象(容器)AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();Student bean = context.getBean(Student.class);//打印对象的值System.out.println(bean);}
测试结果
3.12 导入原生配置文件
导入原生的xml配置文件,原生的xml配置文件,通过注解方式读取该xml配置文件的内容。
<!-- 注解方式读取该bean对象的参数--><bean class="com.lyf.spring5.ioc.entity.Student"><property name="name" value="王二明"/><property name="age" value="18"/></bean>
配置类
@ImportResource
该注解表示读取xml原生配置文件,属性值为xml文件所在的类路径。
@Configuration
@ImportResource(locations = "classpath:context.xml")
public class JavaConfig {}
测试代码
@Testpublic void test1(){//创建spring上下文对象(容器)AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(JavaConfig.class);// context.register(JavaConfig.class);Student student = context.getBean("com.lyf.spring5.ioc.entity.Student",Student.class);//打印对象的值System.out.println(student);}
运行结果
spring5之IOC入门笔记相关推荐
- SpringMVC入门笔记
SpringMVC入门笔记 1. 简介 Spring MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架 ,是Spring系开源项目中的一个,和IoC配合使用.通过 ...
- Spring IOC系列学习笔记五:context:component-scan 节点解析
原文地址程序员囧辉大佬 相关文章 Spring IOC系列学习笔记一:前置刷新 Spring IOC系列学习笔记二:obtainFreshBeanFactory方法 Spring IOC系列学习笔记三 ...
- SpringBootShiro入门笔记
shiro入门笔记 第一章 Shiro简介 1.1 什么是Shiro? 1.2 Shiro框架结构 1.2.1 Shiro主要三大核心注件 1.2.2 主要功能 第二章 认证 2.1 新建一个spri ...
- vue router 入门笔记
vue router 入门笔记 tips: components优先级大于component,即当一个route对象里同时配置了component和components时component视为无效 即 ...
- 十年公务员转行IT,自学AI三年,他淬炼出746页机器学习入门笔记
整理 | Jane 编辑 | Just 出品 | AI科技大本营(ID:rgznai100) 近期,梁劲传来该笔记重大更新的消息.<机器学习--从入门到放弃>这本笔记的更新没有停止,在基于 ...
- html缩进快捷键_HTML 入门笔记
HTML 入门笔记 HTML (HyperText Markup Language) 不是一门编程语言,而是一种用来告知浏览器如何组织页面的标记语言. HTML 可复杂.可简单,一切取决于开发者. 它 ...
- Python3入门笔记(1) —— windows安装与运行
Python3入门笔记(1) -- windows安装与运行 Python的设计哲学是"优雅"."明确"."简单".这也是我喜欢Python ...
- [Java入门笔记] 面向对象编程基础(二):方法详解
2019独角兽企业重金招聘Python工程师标准>>> 什么是方法? 简介 在上一篇的blog中,我们知道了方法是类中的一个组成部分,是类或对象的行为特征的抽象. 无论是从语法和功能 ...
- React.js入门笔记
# React.js入门笔记 核心提示 这是本人学习react.js的第一篇入门笔记,估计也会是该系列涵盖内容最多的笔记,主要内容来自英文官方文档的快速上手部分和阮一峰博客教程.当然,还有我自己尝试的 ...
最新文章
- centos memcached php,centos系统为php安装memcached扩展步骤
- CS224W图机器学习课,斯坦福大牛主讲 | 视频、课件
- 算法训练 素因子去重
- 【开发环境】Mac 安装 PyCharm 开发环境 ( 下载 PyCharm | 安装 PyCharm )
- 个人笔记 vue npm redis
- 液晶面板里面有些什么配件_液晶电视核心部件液晶面板有哪些类型?
- Android Graphic 架构
- mac docker nginx 配置
- 算法分析-堆排序 HeapSort 优先级队列
- 使用adb命令获取手机ip地址
- Msm8960(APQ8064)平台的MSM-AOSP-kitkat编译适配(4):验证代码并编写自己的device
- 批处理——详解%~dp0 %~nx0
- 服务器主机防护系统有哪些,什么是DDoS防护主机?
- android 车牌键盘输入法,支持新能源,警车,军车,领事馆车,特种车辆(源代码)
- EPICS设备支持的简单示例
- 如何将eml格式转换成pdf文档
- 医会宝APP登录体验
- Linux隔离网络,linux – 隔离网络上的单个NTP服务器
- 在3D游戏中显示网页
- k8s集群Deployment与Service+名称空间
热门文章
- 计算机小游戏有哪些,为你解答电脑小游戏有哪些
- oracle取出生僻字显示乱码,python cx_Oracle 查询到生僻字报错问题处理
- 【论文翻译_自监督知识蒸馏】Self-supervised Label Augmentation via Input Transformations
- 【原创】Unity3D 模仿《魔兽世界》的第三人称角色控制器
- rt2870 linux,『求助』RaLink雷凌RT2870 无线网卡怎样安装驱动?
- SWD模式下无法识别到芯片
- LTspice基础教程-022.从MOS管提取参数生成spice模型
- 25款顶级的jQuery表格插件
- i5集显和独显的区别_核显和独显、集成显卡有什么区别,那个好!
- python批量修改文件名称及文件属性