1. Spring-IOC
1.1 Spring对象的生命周期
1.1.1对象的生命周期的说明
-
对象创建
-
初始化数据
-
对象的调用使用
-
销毁对象
核心问题:生命周期内的方法除了实现业务的对象调用都是自动调用的,
测试准备:
编辑测试前的功能类
package com.jt.demo6;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
/*spring自动为该注解标识的类,通过反射实例化对象交给
spring容器管理,类似于@Bean注解
@Component/@Bean区别:
1.@Component spring容器通过反射自动创建对象
@Bean是用户手动自己创建的
2.@Component 标识类的
@Bean 标识类中的方法的
3.@Component 对象的Id的类名首字母小写
@Bean 对象的Id是方法名
*/
@Component
public class User {
//1.对象的创建
public User(){
System.out.println("用户的对象创建成功");
}
//2.进行初始化操作
@PostConstruct//初始化的注解
public void init(){
System.out.println("为属性赋值");
}
//3.进行业务的调用 业务方法,用户手动调用
public void hello(){
System.out.println("我爱学Java~");
}
//4.销毁方法
@PreDestroy
public void destory(){
System.out.println("调用销毁方法,释放资源!!!");
}
}
注解说明:
1.@PostConstruct 标识初始化方法
2.@PreDestroy 标识销毁方法
编辑测试类
注意:容器的接口里面没有提供.close( ),如果需要关闭容器则需要使用实现类中的方法
package com.jt.demo6;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestUser {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SoringConfig.class);
User user = context.getBean(User.class);
User user1 =(User) context.getBean("user");
//调用业务方法
user.hello();
// user1.hello();//两种方法效果一致实现写法不同
//如果需要执行销毁方法,则需要先关闭容器的对象
//思想:销毁动作是敏感行为,特殊处理,实现类中有关闭的方法,接口中没有
context.close();
}
1.2 Spring管理对象-@Component
1.2.1 @Component注解的作用
spring自动为该注解标识的类,通过反射实例化对象交给
spring容器管理,类似于@Bean注解
@Component/@Bean区别:
1.@Component spring容器通过反射自动创建对象 @Bean是用户手动自己创建的 2.@Component 标识类的 @Bean 标识类中的方法的 3.@Component 对象的Id的类名首字母小写 @Bean 对象的Id是方法名
1.2.2 @ComponentScan注解的说明
目的就是为了让Spring的注解生效,需要单独使用包扫描注解
@Configuration//表示配置类
@ComponentScan("com.jt.demo6")//包扫描
public class SoringConfig {}
2. Spring-DI(Dependency Injection)
2.1 Spring中的依赖注入
说明:依赖注入就是将Spring容器管理对象(数据),赋值给对象的属性
核心机制:如果需要使用依赖注入,则对象的属性必须要提供set方法
2.2 xml配置文件的写法
2.2.1 编辑Person类
package com.jt.demo7_id;
public class Person {
private int id;
private String name;
public void sayHi(){
System.out.println("你好呀"+id+name);
}
public int getId() {
return id;
}
//为属性赋值必须要有set方法!!!重中之重
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2.2.2 编辑xml配置文件
配置属性是使用的<property/>标签
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
知识点讲解:
1.bean 被spring容器管理的对象称之为bean
2.id 全局唯一变量一般类型首字母小写
3.class class的路径信息,需要写全名
-->
<!--xml配置文件为属性赋值-->
<bean id="person" class="com.jt.demo7_id.Person">
<property name="id" value="100"></property>
<property name="name" value="新年快乐"></property>
<property name="car" ref="car"></property>
</bean>
2.2.3 编辑测试类
package com.jt.demo7_id;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
@Component//将类交给Spring容器管理
public class TersPerson {
public static void main(String[] args) {
//创建容器对象
ApplicationContext context = new ClassPathXmlApplicationContext("spring_id.xml");
// ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring_id.xml");
//从容器中获取对象
Person bean = context.getBean(Person.class);
//调用业务方法
bean.sayHi();
// context.close();//关流操作
}
}
2.3 Spring为对象赋值
2.3.1 构造Car对象
package com.jt.demo7_id;
public class Car {
private String name;
private String color;
public void go(){
System.out.println("上我的"+color+"的"+name+"带你去浪漫的土耳其~");
}
public Car(){
System.out.println("无参构造方法");
}
public Car(String name,String color){
this.name=name;
this.color=color;
System.out.println("全参构造方法");
}
}
2.3.2 编辑xml配置文件
管理对象是使用的<constructor-arg/>标签
<!--1.让spring容器管理car,参数的个数,决定调用的构造方法-->
<bean id="car" class="com.jt.demo7_id.Car">
<constructor-arg name="name" value="奥迪RS8"></constructor-arg>
<constructor-arg name="color" value="绿色"></constructor-arg>
</bean>
2.3.3补充构建Person类
package com.jt.demo7_id;
public class Person {
private int id;
private String name;
private Car car;
public void sayHi(){
System.out.println("你好呀"+id+name);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
public void toGo(){
car.go();
}
}
2.3.4 编辑测试类
package com.jt.demo7_id;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
@Component
public class TersPerson {
public static void main(String[] args) {
//创建容器对象
ApplicationContext context = new ClassPathXmlApplicationContext("spring_id.xml");
// ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring_id.xml");
//从容器中获取对象
Person bean = context.getBean(Person.class);
//调用业务方法
bean.sayHi();
bean.toGo();
// context.close();//关流操作
}
}
2.3.5 IOC/DI意义
我的理解:Spring中的IOC(控制反转)/DI(依赖注入)两种方式相互配合,实现了代码的解耦/松耦合
2.4 注入的方式说明
2.4.1 Set方法注入
说明:通过set方法为属性赋值,所以必须提供set方法才行,xml配置文件中使用的是property标签,开发中常用的是set方法注入
2.4.2 构造方法注入
说明:通过构造方法为属性赋值,所以需要提供构造方法,提醒手动写上无参构造,使用的是constructor -arg标签.
<!--1.让spring容器管理car,参数的个数,决定调用的构造方法-->
<bean id="car" class="com.jt.demo7_id.Car">
<constructor-arg name="name" value="奥迪RS8"></constructor-arg>
<constructor-arg name="color" value="绿色"></constructor-arg>
</bean>
备注:Ste和构造方法为属性赋值都是常规写法,没有好坏之分,自己习惯用哪个就行,set注入以后用的多些
2.5 Spring属性赋值-注解用法@Autowired
2.5.1编辑配置类
package com.jt.demo8_anno;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration//标记为配置类
@ComponentScan("com.jt.demo8_anno")//包扫描
public class SpringConfig {
}
2.5.2 编辑Tiger类
package com.jt.demo8_anno;
import org.springframework.stereotype.Component;
//对象套对象
@Component//将该对象交给spring容器管理,key:tiger value:tiger对象
public class Tiger implements Pet{
@Override
public void hello() {
System.out.println("虎年吉祥~");
}
}
2.5.3 编辑User类
package com.jt.demo8_anno;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
/**
* 1.该类主要测试 注解的注入方式
* 2.练习对象的嵌套关系
* 3.注解的写法与xml写法的原理相同的,形式不同
* */
@Component//把user交给spring容器管理 key:user value:反射后的对象
public class User {//用户
/**
* 注解说明:
* 1.@Autowired 自动注入
* 规则:
* 1.默认条件下,底层是使用set方法注入.按照类型匹配
* 2.set方式注入也可以按照name名称进行匹配
* 3.只要使用了这个注解,默认自动生成setxxx的方法
* 实现原理:
* 1.类型匹配 如果是接口,则自动匹配其实现类对象
* 2.name名称匹配:根据spring中的key进行注入.
* 2.@Qualifier
* 必须和 @Autowired联用,
* 并且需要指定value的名称,就是spring中的key
*
* 准则:一般情况下,Spring中都是单实现的
**/
@Autowired
@Qualifier("pig")
private Pet pet;
public void hello(){
pet.hello();
}
}
2.5.4 编辑测试类
package com.jt.demo8_anno;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestUser {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
User user = context.getBean(User.class);
user.hello();
}
}
总结:使用注解开发后能够明显感觉到代码量少了很多,这也是注解的一大特性,减少代码冗余
2.6 拓展:多实现类的情况处理
2.6.1 异常说明
Spring中的DI注入,一般情况下采用按照类型的方式进行匹配,但是如果遇到了多实现类的情况,就会出现,报错: 一个接口匹配了多个实现类,程序异常
原因:这个是由于程序是不会自动做选择的,当面临多个选择的时候,它不知道到底选哪个所以直接报错
2.6.2 指定key进行赋值
package com.jt.demo8_anno;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
/**
* 1.该类主要测试 注解的注入方式
* 2.练习对象的嵌套关系
* 3.注解的写法与xml写法的原理相同的,形式不同
* */
@Component//把user交给spring容器管理 key:user value:反射后的对象
public class User {//用户
/**
* 注解说明:
* 1.@Autowired 自动注入
* 规则:
* 1.默认条件下,底层是使用set方法注入.按照类型匹配
* 2.set方式注入也可以按照name名称进行匹配
* 3.只要使用了这个注解,默认自动生成setxxx的方法
* 实现原理:
* 1.类型匹配 如果是接口,则自动匹配其实现类对象
* 2.name名称匹配:根据spring中的key进行注入.
* 2.@Qualifier
* 必须和 @Autowired联用,
* 并且需要指定value的名称,就是spring中的key
*
* 准则:一般情况下,Spring中都是单实现的
**/
@Autowired
@Qualifier("pig")
private Pet pet;
public void hello(){
pet.hello();
}
}
2.7 Spring属性赋值-@Value注解
2.7.1编辑properties配置文件
创建一个dept.properties文件
#1.数据结构 key = value
#2.其中的数据默认都是String类型,数值可以切换为Integer数值类型
#3.程序读取时,默认的字符集ISO-8859-1,不支持中文,如需要使用UTF-8
dept.id=101
dept.name=行政部
2.7.2 为属性赋值操作
package com.jt.demo9;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@Component
//当spring容器启动的时候,加载指定的配置文件,将数据保存到容器中!!!
@PropertySource(value = "classpath:/dept.properties",encoding = "utf-8")
public class Dept {
//取值方式:从spring容器中获取数据 ${pro中的key}
@Value("${dept.id}")
private Integer id;
@Value("${dept.name}")
private String name;
// @Value("101")
//private Integer id;
//@Value("财务部")
//private String name;
public void hello(){
System.out.println("获取数据"+id+name);
}
2.7.3 编辑测试类
package com.jt.demo9;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestDept {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
Dept dept = context.getBean(Dept.class);
dept.hello();
}
}
注解总结: 本章用到了哪些新的注解呢?
1.@ComponentScan 标记于类,包扫描,目的是为了让Spring中的注解生效
2.@PostConstruct 标记于方法,初始化注解
3.@PreDestory 标记于方法,用于销毁对象
4.@Component 标记于类,用于表示将本类交于Spring容器管理
5.@Autowired 标记于属性,按照类型注入,底层是使用的set注入,只要使用了这个注解,默认自动生成setxxx的方法不用手写
6.@Qualifier 标记于属性,按照名称注入,使用前提是需要有@Autowired ,并且需要指定value的名称,就是spring中的key,不可单独使用
7.@Value 标记于属性,格式${properties文件中的key值}
8.@PropertySource 标记于类,当spring容器启动的时候,加载指定的配置文件,将数据保存到容器中