1.什么是Bean?
- Bean是被实例的、组装的、及被Spring容器管理的Java对象。
- Spring容器会自动完成Bean对象的实例化。
- 创建应用对象之间的协作关系的行为被称为:装配,这就是依赖注入的本质。
2.Spring三种装配方案
1.隐式的bean发现机制和自动装配;
- 1.涉及注册Bean的注解:@Component , @Repository , @ Controller , @Service , @Configration;(这些注解只局限于自己编写的类)。
- 2.使用Bean的注解:@Autowired(默认byType注入,跟@Qualifier(“bean名称”)搭配进行byName注入), @Resource(默认byName注入,可以设置为byType);
- 3.指定要扫描的包:@CompoentScan(“要扫描的包名”),后边没参数时,默认扫描当前包、及其子包。
2.使用Java代码进行显示配置;
- 1.涉及注解:@Bean,当引入第三方组件时,就需要用它去返回一个对象。
- 2.@Bean注解用在返回实例的方法上,告诉方法,产生一个Bean对象,然后这个Bean对象交给Spring管理。 产生这个Bean对象的方法Spring只会调用一次。
- 3.@Import也能把第三方库中的类实例交给spring管理
3.在xml文件中进行显示配置。(不展开)
3.关于Bean的命名
- 1.默认是类名的首字母小写。
下边的bean默认的ID名:jayDisc
@Component
public class JayDisc implements ICompactDisc {...
}
- 2.或者自己指定
下边bean的ID名:zhoujielun
@Component("zhoujielun")
public class JayDisc implements ICompactDisc {...
}
3.5.Spring的常用注入方式
- 1.构造器的依赖注入
- 2.Setter方法的注入
- 3.基于注解的注入,最好的解决方案是用构造器参数,实现强制依赖,Setter方法实现可选依赖。
4.关于自动注入——以@Autowire为例
1.源码
- 属性boolean required();表示,如果没找到依赖注入的对象是否报错?
可以自己设置为false,不报错,但是一旦用到没被注入的对象会报NullPonterException空指针异常。
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {* Declares whether the annotated dependency is required.* <p>Defaults to {@code true}.这个属性表示,如果没找到依赖注入的对象是否报错?boolean required() default true;}
2.用法,3个地方
- 1.用在构造器上(@Resource不支持这个)
public class Student {private Integer age;private String name;@Autowiredpublic Student(Integer age, String name) {this.age = age;this.name = name;}
}
- 2.属性setter注解
public class Student {private Integer age;private String name;@Autowiredpublic void setAge(Integer age) {this.age = age;}@Autowiredpublic void setName(String name) {this.name = name;}
}
- 3.属性field注解
public class Student {@Autowiredprivate Integer age;@Autowiredprivate String name;
}
5.Java对象的创建
1.对象创建的3步骤
1.为对象分配内存空间;
2.初始化对象;
3.将对象指向 分配的内存地址。
2.代码的执行顺序
父类静态代码块 >> 子类静态代码块 >> 父类代码块 >> 父类构造方法 >> 子类代码块 >> 子类构造方法
1.如下代码,子类调用了父类的构造方法。
- 1.父类静态代码块……(只执行1次)
- 2.子类静态代码块……(只执行1次)
- 3.父类代码块……(每次new对象都执行)
- 4.父类构造方法……(每次new对象都执行)
- 5.子类代码块……(每次new对象都执行)
- 6.子类构造方法……(每次new对象都执行)
class Parent{int age ;static {System.out.println("父类静态代码块……");}{System.out.println("父类代码块……");}public Parent(int age) {System.out.println("父类构造方法……");this.age = age;}
}
class Child extends Parent{static {System.out.println("子类静态代码块……");}{System.out.println("子类代码块……");}public Child(int age) {super(age); 调用父类构造方法System.out.println("子类构造方法……");}
}
2.如下代码,没有调用父类的构造方法
- 1.父类静态代码块……(只执行1次)
- 2.子类静态代码块……(只执行1次)
- 3.父类代码块……(每次new对象都执行)
- 4.子类代码块……(每次new对象都执行)
- 5.子类构造方法……(每次new对象都执行)
class Parent{int age ;static {System.out.println("父类静态代码块……");}{System.out.println("父类代码块……"+age);}public Parent(int age) {System.out.println("父类构造方法……"+age);this.age = age;}public Parent() {}
}
class Child extends Parent{static {System.out.println("子类静态代码块……");}{System.out.println("子类代码块……"+age);}public Child(int age) {System.out.println("子类构造方法……"+age);this.age = age;}public Child() {}
}
6.Bean的生命周期
6.1.Spring扫描获取BeanDefinition
一个BeanDefinition描述了一个Bean实例的相关信息:属性、是否单例、是否懒加载、父类名称等;
6.2.Spring根据BeanDefinition进行实例化
实例化对象被包装在BeanWrapper对象(此时对象仍然是一个原生的状态,并没有进行依赖注入)中,之后通过BeanWrapper提供的设置属性的接口完成依赖注入。
6.3.注入Aware接口
- 什么是Aware接口????:
- 实现xxxAware接口,bean才有被Spring容器通知的能力,才能调用Spring所提供的资源;
- 因为Bean对Spring容器的存在是没有意识的,所以不实现xxAware接口,就没办法调用Spring的资源。
检测该对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给Bean;
- BeanNameAware,获取容器中当前Bean的名称;
- BeanFactoryAware,获取BeanFactory
- ApplicationContextAware,获取ApplicationContext(它是BeanFactory的子类,IoC的核心)
- 此类可以获取到spring配置文件中所有的bean对象
- 此类可以获取到spring配置文件中所有的bean对象
6.4.检查Bean是否实现BeanPostProcessor接口
该接口有两个方法:一个实例化Bean之前调用,一个实例化Bean之后调用
- 入参:要处理的Bean对象,Bean的名字
- 出参:要处理的Bean对象
前置处理:postProcessBeforeInitialzation,在InitialzationBean之前执行,因此称为前置处理。所有Aware接口的注入就是在这一步完成的。
后置处理:postProcessAfterInitialzation,在InitialzationBean之后执行,因此称为后置处理。
public interface BeanPostProcessor {@Nullable1.实例化之前调用default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}@Nullable2.实例化之后调用default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;}
}
6.5.InitializingBean接口与init-method:实现注入Bean的初始化的2种方法
在bean正式构造完成前增加我们自定义的逻辑。
- 1.实现InitializingBean接口,则实现afterProperties的方法;
public interface InitializingBean {void afterPropertiesSet() throws Exception;
}
- 2.反射原理,配置文件使用init-method标签直接注入bean。本质上仍然使用了InitializingBean接口。
6.6.DisposableBean接口和deatroy-method;2种方法异曲同工
在bean销毁前执行自定义的逻辑。
- 1.容器关闭后,如果Bean实现了DisposableBean接口,则会调用该接口的destroy方法;
public interface DisposableBean {void destroy() throws Exception;
}
- 2.如果配置了destroy-method方法,则会执行destroy-method配置的方法。
7.Bean的作用域——@Scope注解
1.Singleton:唯一的Bean实例,Spring默认bean是单例的;
@Scope("singleton")
2.Prototype:每次注入或者通过Spring应用上下文获取都会创建1个新的Bean实例;
@Scope("prototype")
3.Session:在web应用中,为每个会话创建1和Bean实例,只在本次会话的生命周期中生存;
4.Request:在web应用中,为每个请求创建1和Bean实例;只在本次请求的生命周期中生存;
8.FactoryBean与BeanFactory区别
BeanFactory,是Bean的工厂,ApplicationContext的父类,IoC容器的核心,负责生产和管理Bean对象;
FactoryBean,它只是1个Bean,可以通过实现FactoryBean接口定制实例化Bean的逻辑。
9.ApplicationContext的通常实现
- 1.FileSystemXmlApplicationContext
此容器从⼀个 XML ⽂件中加载beans 的定义,XML Bean 配置⽂件的全路径名必须提供给它的构造函数。 - 2.ClassPathXmlApplicationContext
此容器也从⼀个 XML ⽂件中加载beans 的定义,这⾥,你需要正确设置classpath 因为这个容器将在 classpath ⾥找 bean 配置。