【本文为bilibili视频雷丰阳的Spring源码解析的完整版总结文章,其中文章前面大部分为他人博文的搬运,后面补充了其未总结的部分】
注释:用文字描述程序,给程序员看的;
注解:说明程序的,给计算机看的。
注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
概念描述:
作用分类:
/**
1. 注解javadoc演示
2. 3. @version 1.0
4. @since 1.5
*/
public class AnnoDemo1 {
/**
* 计算两数的和
* @param a 整数
* @param b 整数
* @return 两数的和
*/
public int add(int a, int b ){
return a + b;
}
}
JDK中预定义的一些注解:
@Override
:检测被该注解标注的方法是否是继承自父类(接口)的@Deprecated
:该注解标注的内容,表示已过时@SuppressWarnings
:压制警告。一般传递参数all,@SuppressWarnings("all")
格式:
public @interface 注解名称{
属性列表;
}
本质:注解本质上就是一个接口,该接口默认继承Annotation接口
public interface MyAnno extends java.lang.annotation.Annotation {}
属性:接口中的抽象方法
属性的返回值值类型有如下取值:
public @interface MyAnno {
int value();
Person per();
MyAnno2 anno2();
String[] strs();
String name() default "张三";
}
定义了属性,在使用时需要给属性赋值:
default
关键字给属性默认初始值,则在使用注解,可以不进行属性的赋值;value
,则value
可以忽略,直接定义值即可;{}
包裹。如果数组中只有一个值,则{}
可以省略。@MyAnno(value=12, per = Person.P1, anno2 = @MyAnno2, strs="bbb")
public class Worker {
}
元注解: 用于描述注解的注解
@Target:描述注解能够给作用的位置。
ElementType取值:
@Retention:描述注解被保留的阶段
value 是 java.lang.annotation.RetentionPolicy 枚举类型, RetentionPolicy 有 3 个枚举常量,如下所示:
@Retention(RetentionPolicy.RUNTIME):当前被描述的注解,会保留到class字节码文件中,并被JVM读取到。
@Documneted:描述注解是否被抽取到API文档中
@Inherited:描述注解是否被子类继承
@Target({
ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface MyAnno3 {
}
@MyAnno3
public class Worker {
@MyAnno3
public String name = "aaa";
@MyAnno3
public void show(){
}
}
在程序使用(解析)注解:获取注解中定义的属性值。
@Pro(className = "top.tjtulong.annotation.Demo1",methodName = "show")
public class ReflectTest {
public static void main(String[] args) throws Exception {
Pro an = reflectTestClass.getAnnotation(Pro.class);
// 调用注解对象中定义的抽象方法,获取返回值
String className = an.className();
String methodName = an.methodName();
System.out.println(className);
System.out.println(methodName);
}
}
getAnnotation(Class)
,其实就是在内存中生成了一个该注解接口的子类实现对象。public class ProImpl implements Pro{
public String className(){
return "top.tjtulong.annotation.Demo1";
}
public String methodName(){
return "show";
}
}
@Configuration
:指定配置类;
@Component
:用于把当前类对象存入spring容器中;
以下三个注解的作用与@Component完全一样,它们是spring提供的更明确的划分,使三层对象更加清晰:
@Controller
:用于表现层;@Service
:用于业务层;@Repository
:用于持久层;@Bean
:给容器中注册一个Bean对象,类型为返回值的类型,id默认是用方法名作为id;
@ComponentScan
:指明注解扫描的包,属性包括:
@Filter()
来具体指定userDefaultFilters=false
,才能生效)
FilterType.ANNOTATION:按照注解类型过滤
FilterType.ASSIGNABLE_TYPE:按照给定的类型过滤
FilterType.ASPECTJ:使用ASPECTJ表达式过滤
FilterType.REGEX:使用正则指定
FilterType.CUSTOM:使用自定义规则过滤
原先使用bean.xml配置时,还需先将默认属性设置成 use-defalut=false ,即禁用默认扫描规则。
@ComponentScans
:指明多个@ComponentScan
扫描的包;
@Scope
:调整Bean实例的作用域,共有4种:
@Lazy
:懒加载,容器启动不创建对象(抑制了singleton原本的加载方式),第一次获取Bean时再创建对象并初始化;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.ComponentScans;
import top.tjtulong.bean.Person;
// 配置类==配置文件
@Configuration // 告诉Spring这是一个配置类
@ComponentScans(
value = {
@ComponentScan(value="top.tjtulong",includeFilters = {
@Filter(type=FilterType.ANNOTATION, classes={
Controller.class}),
@Filter(type=FilterType.ASSIGNABLE_TYPE, classes={
BookService.class}),
@Filter(type=FilterType.CUSTOM, classes={
MyTypeFilter.class})
},useDefaultFilters = false)
}
)
public class MainConfig {
//给容器中注册一个Bean,类型为返回值的类型,id默认是用方法名作为id
@Scope("prototype")
@Bean("person")
public Person person01(){
return new Person("lisi", 20);
}
}
public class Person {
private String name;
private Integer age;
//get() set() toString()...
}
自定义的包扫描过滤规则
public class MyTypeFilter implements TypeFilter {
/**
* metadataReader:读取到的当前正在扫描的类的信息
* metadataReaderFactory:可以获取到其他任何类信息的
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
// TODO Auto-generated method stub
//获取当前类注解的信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前正在扫描的类的类信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//获取当前类资源(类的路径)
Resource resource = metadataReader.getResource();
String className = classMetadata.getClassName();
System.out.println("--->"+className);
if(className.contains("er")){
return true;
}
return false;
}
}
@Condition
:按照一定的条件进行判断,满足条件给容器中注册bean,可以放在类上,也可以放在方法上;
@Import
:导入组件,id默认是 组件的全类名;
//类中组件统一设置,满足当前条件,这个类中配置的所有bean注册才能生效;
// @Conditional({WindowsCondition.class})
@Configuration
// MyImportSelector:自定义导入逻辑
// @Import({Color.class, Red.class, MyImportSelector.class})
@Import({
Color.class, Red.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig2 {
/**
* 如果系统是windows,给容器中注册("bill")
* 如果是linux系统,给容器中注册("linus")
*/
@Conditional({
WindowsCondition.class})
@Bean("bill")
public Person person01(){
return new Person("Bill Gates",62);
}
@Conditional({
LinuxCondition.class})
@Bean("linus")
public Person person02(){
return new Person("linus", 48);
}
}
Condition 类:
//判断是否linux系统
public class LinuxCondition implements Condition {
/**
* ConditionContext:判断条件能使用的上下文(环境)
* AnnotatedTypeMetadata:注释信息
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// TODO是否linux系统
//1、能获取到ioc使用的beanfactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//2、获取类加载器
ClassLoader classLoader = context.getClassLoader();
//3、获取当前环境信息
Environment environment = context.getEnvironment();
//4、获取到bean定义的注册类
BeanDefinitionRegistry registry = context.getRegistry();
//可以判断容器中的Bean注册情况,也可以给容器中注册bean
boolean definition = registry.containsBeanDefinition("person");
String property = environment.getProperty("os.name");
if(property.contains("linux")){
return true;
}
return false;
}
}
实现ImportSelector
自定义逻辑导入需要的组件
//自定义逻辑返回需要导入的组件
public class MyImportSelector implements ImportSelector {
//返回值,就是要导入到容器中的组件的全类名
//AnnotationMetadata:当前标注 @Import 注解的类的所有注解信息
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//默认不要返回null
//全类名
return new String[]{
"com.atguigu.bean.Blue","com.atguigu.bean.Yellow"};
}
}
实现 ImportBeanDefinitionRegistrar
手动注册bean到容器中:
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
* AnnotationMetadata:当前类的注解信息
* BeanDefinitionRegistry:BeanDefinition注册类;
* 把所有需要添加到容器中的bean;
* 调用BeanDefinitionRegistry.registerBeanDefinition手工注册进来
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean definition = registry.containsBeanDefinition("top.tjtulong.bean.Red");
boolean definition2 = registry.containsBeanDefinition("top.tjtulong.bean.Blue");
if(definition && definition2){
//指定Bean定义信息
//RootBeanDefinition 为接口BeanDefintion的实现
RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class);
//注册一个Bean,指定bean名
registry.registerBeanDefinition("rainBow", beanDefinition);
}
}
}
给容器中注册组件方法汇总:
@Controller/@Service/@Repository/@Component
)[自己写的类]@Bean
[导入的第三方包里面的组件]@Import
[快速给容器中导入一个组件]
@Import
(要导入到容器中的类);容器中就会自动注册这个组件,id默认是全类名;ImportSelector
:返回需要导入的组件的全类名数组;ImportBeanDefinitionRegistrar
:手动注册bean到容器中;FactoryBean
(工厂Bean);
getObject()
创建的对象;&colorFactoryBean
); 否则,获取的是getObject()方法返回值对象。@Bean
public ColorFactoryBean colorFactoryBean(){
//返回的虽然是colorFactoryBean,但其为com.titjlong.bean.Color类型
//工厂bean的获取最终会调用getObject(),以其返回值类型为准
return new ColorFactoryBean();
}
//创建一个Spring定义的FactoryBean
public class ColorFactoryBean implements FactoryBean<Color> {
//返回一个Color对象,这个对象会添加到容器中
@Override
public Color getObject() throws Exception {
System.out.println("ColorFactoryBean...getObject...");
return new Color();
}
@Override
public Class<Color> getObjectType() {
return Color.class;
}
//是否为单例
@Override
public boolean isSingleton() {
return false;
}
}
bean 的生命周期是指:bean的创建 ---> 初始化 ---> 销毁的过程
方法一:通过@Bean
指定初始化和销毁方法
initMethod
:初始化方法;destroyMethod
:销毁方法。
@Component
public class Car {
public Car(){
System.out.println("car constructor...");
}
public void init(){
System.out.println("car ... init...");
}
public void detory(){
System.out.println("car ... detory...");
}
}
@ComponentScan("top.tjtulong.bean")
@Configuration
public class MainConfigOfLifeCycle {
//@Scope("prototype")
@Bean(initMethod="init", destroyMethod="detory")
public Car car(){
return new Car();
}
}
构造(对象创建):
单实例 singleton:在容器启动的时候创建对象
多实例 prototype:在每次获取的时候创建对象
初始化:对象创建完成,并赋值好,调用初始化方法。
销毁:
单实例 singleton:容器关闭的时候销毁
多实例 prototype: 容器不会管理这个bean; 容器不会调用销毁方法。
方法二:通过让Bean实现InitalizingBean
接口(定义初始化逻辑)afterPropertiesSet()
方法,DisposableBean
接口(定义销毁逻辑)destroy()
方法
@Component
public class Cat implements InitializingBean,DisposableBean {
public Cat(){
System.out.println("cat constructor...");
}
@Override
public void destroy() throws Exception {
System.out.println("cat...destroy...");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("cat...afterPropertiesSet...");
}
}
方法三:可以使用JSR250
@PostConstruct
:在bean创建完成并且属性赋值完成,来执行初始化方法;作用于方法层面@Target(METHOD)
@PreDestroy
:在容器销毁bean之前通知我们进行清理工作;@Component
public class Dog implements ApplicationContextAware {
public Dog(){
System.out.println("dog constructor...");
}
//对象创建并赋值之后调用
@PostConstruct
public void init(){
System.out.println("Dog....@PostConstruct...");
}
//容器移除对象之前
@PreDestroy
public void detory(){
System.out.println("Dog....@PreDestroy...");
}
}
以上三种初始化方法的执行顺序为:Constructor > @PostConstruct >InitializingBean接口(afterPropertiesSet) > initMethod
三种销毁方法的执行顺序为:@preDestroy >DisposableBean接口 > @Bean(destroyMethod)
方法四:BeanPostProcessor接口(bean的后置处理器)
在bean初始化前后进行一些处理工作:
postProcessBeforeInitialization
:在初始化之前工作,在上面三个方法执行前执行postProcessAfterInitialization
:在初始化之后工作,在上面三个方法执行后执行/**
* 后置处理器:初始化前后进行处理工作
* 将后置处理器加入到容器中
*/
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
/**
* @param bean the new bean instance
* @param beanName the name of the bean
**/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization..."+beanName+"=>"+bean);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization..."+beanName+"=>"+bean);
return bean;
}
}
在refresh()
方法中的 finishBeanFactoryInitialization(beanFactory)
方法执行时,bean进行初始化。
step1:populateBean(beanName, mbd, instanceWrapper)
;给bean进行属性赋值
step2:initializeBean()
;初始化bean对象
initializeBean()
: wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
invokeInitMethods(beanName, wrappedBean, mbd); //执行自定义初始化
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
在方法applyBeanPostProcessorBeforeInitialization
中:会遍历得到容器中所有的BeanPostProcessor
,逐个执行BeanPostProcessor.postProcessorBeforeInitialization()
方法,一但返回null,跳出for循环,直接返回,不会执行后面的方法 。
【BeanProstProcessor在Spring底层的使用】
ApplicationContextAware
接口获取ioc容器,底层通过ApplicationContextAwareProcessor
实现public class Dog implements ApplicationContextAware {
private ApplicationContext applicationContext;
public Dog(){
System.out.println("dog constructor....");
}
@PostConstruct
public void init(){
System.out.println("Dog...@PostConstruct");
}
@PreDestroy
public void destory(){
System.out.println("Dog...@PreDestory");
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
p.s. bean的赋值、注入其它组件、@Autowired、初始化注解、生命周期注解功能@PreConstruct等、@Async等功能都是通过BeanPostProcessor
实现。
使用@Value
赋值
基本数值
可以写SpEL:#{}
可以写${}
,去取配置文件【properties】中的值(在运行环境变量Environment 里面的值)
#{} 和 ${} 的区别 可以参看
#{}
1. #{}属于SPEL语法。如#{dataSource.userName}给某个属性赋值时,dataSource是程序中已经注入存在的Bean容器, 则可以通过 @value(#{dataSource.userName}) 获取属性的值。
2. #{} mybatis中使用它相当于占位符的用法。如#{name} 可以自动进行jdbc类型的属性转换,如果name的值是 mark 则转换之后就是 'mark',它可以防止sql注入。
${}
3. ${server.port} 取配置文件中的配置值,如 server.port=80 则可以通过 @value(${server.port}) 来获取属性的值。
4. ${} mybatis中使用它相当于不做单引号任何处理, 如${name},如果name的值是 create_time,则转换之后就是 order by create_time ,不做处理直接拼接,不能防止sql注入,另外的场景也有模糊查询 like '%${name}%'
public class Person {
@Value("张三")
private String name;
@Value("#{20-2}")
private Integer age;
@Value("${person.nickName}")
private String nickName;
}
配置类
// 使用@PropertySource读取外部配置文件中的k/v保存到运行的环境变量中;
// 加载完外部的配置文件以后使用${}取出配置文件的值
@PropertySource(value={
"classpath:/person.properties"})
@Configuration
public class MainConfigOfPropertyValues {
@Bean
public Person person(){
return new Person();
}
}
针对Property的取值,也可以直接再环境变量Environment
中取
ConfigurableEnvironment environment = applicationContext.getEnvironment();
String property = environment.getProperty("person.nickName");
System.out.println(property);
自动装配:Spring利用依赖注入(DI),完成对IOC容器中各个组件的依赖关系赋值。
@Autowired
:自动注入,可以放在构造器,参数,方法,属性上
默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class)
,找到就赋值;
如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找。
BookService {
@Autowired
BookDao bookDao;
}
//默认加在ioc容器中的组件,容器启动会调用无参构造器创建对象,再进行初始化赋值等操作
@Component
public class Bosss{
private Car car;
public Car getCar(){
return car;
}
@Autowired
//标注在方法上,Spring容器创建当前对象,就会调用方法,完成赋值
//方法使用的参数,自定义类型的值从ioc容器中获取
public void setCar(Car car){
this.car = car;
}
}
@Bean
标注的方法创建对象时,方法参数的值从容器中获取,默认不写@Autowired
public class Color{
private Car car;
//以下省略get/Set方法
}
//方法参数Car,会自动从容器中获取
@Bean
public Color color(Car car){
Color color = new Color();
color.setCar(car);
return new Color();
}
//默认加在ioc容器中的组件,容器启动会调用无参构造器创建对象,再进行初始化赋值等操作
@Component
public class Bosss{
private Car car;
//构造器要用的组件,都是从容器中获取
@Autowired
public Boss(Car car){
this.car = car;
}
public Car getCar(){
return car;
}
public void setCar(Car car){
this.car = car;
}
}
//默认加在ioc容器中的组件,容器启动会调用无参构造器创建对象,再进行初始化赋值等操作
@Component
public class Bosss{
private Car car;
//放在参数上
public Boss(@Autowired Car car){
this.car = car;
}
public void setCar(Car car){
this.car = car;
}
}
@Qualifier("bookDao")
:使用@Qualifier指定需要装配的组件的id,而不是使用属性名;
自动装配默认一定要将属性赋值好,没有就会报错;可以使用@Autowired(required=false)
;
@Primary
用于在有多个同类型对象的实例Bean下,指明首选装配的对象。优先装配标有@Primary
的Bean,此时@Qualifier
不使用。
Spring还支持使用@Resource
(JSR250)和@Inject
(JSR330) [java规范的注解]:
@Resource
:可以和@Autowired
一样实现自动装配功能,默认是按照组件名称进行装配的;但没有能支持@Primary
功能,也没有支持@Autowired(reqiured=false)
;
@Inject
:需要导入javax.inject的依赖包,和@Autowired
的功能一样,但没有required=false
的功能;
p.s. @Autowired是Spring定义的;而@Resource、@Inject都是Java的规范。
以上注解功能,都是通过AutowiredAnnotationBeanPostProcessor解析完成自动装配功能。
自定义组件想要使用Spring容器底层的一些组件(如:ApplicationContext,BeanFactory,…等)
自定义组件需要实现相应的xxxAware接口:在创建对象的时候,会调用接口规定的方法注入相关的组件。
在Spring中有很多以Aware结尾的接口,如果一个Bean实现了该接口,那么当该Bean被Spring初始化时,Spring会向该Bean注入相关资源(就是会回调接口中的方法)。作用是把Spring底层一些组件注入到自定义的Bean中。
示例:下面的TestService
实现了两个接口BeanNameAware
和ApplicationContextAware
接口。当Spring对bean进行初始化时,Spring会调用接口对应得方法。这样就可以获得spring中的资源。
@Component
public class TestService implements BeanNameAware,ApplicationContextAware {
private String beanName;
private ApplicationContext context;
@Override
// 获取到bean的名称
public void setBeanName(String name) {
System.out.println("name = " + name);
beanName = name;
}
@Override
// 获取上下文环境ApplicationContext
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("applicationContext = " + applicationContext);
context = applicationContext;
}
}
Aware子接口及作用: 参考
接口名称 | 作用 |
---|---|
ApplicationContextAware | 获取spring 上下文环境的对象 |
ApplicationEventPublisherAware | 事件发布器 |
BeanClassLoaderAware | 加载Spring Bean的类加载器 |
BeanNameAware | 获取该bean在BeanFactory配置中的名字 |
BeanFactoryAware | 创建它的BeanFactory实例 |
EmbeddedValueResolverAware | 手动读取配置参数值 |
EnvironmentAware | 环境变量读取和属性对象获取 |
ImportAware | 处理自定义注解 |
LoadTimeWeaverAware | 加载Spring Bean时植入第三方模块,如AspectJ |
MessageSourceAware | 国际化 |
NotificationPublisherWare | JMX通知 |
ResourceLoaderAware | 获取ResourceLoader对象,通过它获得各种资源 |
ApplicationContextAware通过ApplicationContextAwareProcessor实现。
具体实现参考:https://blog.csdn.net/baidu_19473529/article/details/81072524
@Profile
:指定组件在哪个环境的情况下才能被注册到容器中,若不指定,任何环境下都能注册这个组件。
便于开发环境、测试环境、生产环境之间的切换
@PropertySource("classpath:/dbconfig.properties")
@Configuration
public class MainConfigOfProfile implements EmbeddedValueResolverAware{
@Value("${db.user}")
private String user;
private StringValueResolver valueResolver;
private String driverClass;
@Profile("test")
@Bean("testDataSource")
public DataSource dataSourceTest(@Value("${db.password}")String pwd) throws Exception{
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(pwd);
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
dataSource.setDriverClass(driverClass);
return dataSource;
}
@Profile("dev")
@Bean("devDataSource")
public DataSource dataSourceDev(@Value("${db.password}")String pwd) throws Exception{
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(pwd);
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/ssm_crud");
dataSource.setDriverClass(driverClass);
return dataSource;
}
@Profile("prod")
@Bean("prodDataSource")
public DataSource dataSourceProd(@Value("${db.password}")String pwd) throws Exception{
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(pwd);
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/scw_0515");
dataSource.setDriverClass(driverClass);
return dataSource;
}
@Override
// 处理${}等特殊字符
public void setEmbeddedValueResolver(StringValueResolver resolver) {
this.valueResolver = resolver;
driverClass = valueResolver.resolveStringValue("${db.driverClass}");
}
}
设置运行时设置profile的方式:
-Dspring.profiles.active=dev
//1、使用无参构造创建一个applicationContext
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext();
//2、设置需要激活的环境
applicationContext.getEnvironment().setActiveProfiles("dev");
//3、注册主配置类
applicationContext.register(MainConfigOfProfile.class);
//4、启动刷新容器
applicationContext.refresh();
AOP动态代理:指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式。
step:
导入Spring-AOP模块:spring-aspects;
定义一个业务逻辑类(如:MathCalculator类),在业务逻辑运行的时候将日志进行打印(方法执行之前、方法运行结束、方法出现异常,方法返回前);
定义一个日志切面类(如LogAspects),切面类里面的方法需要动态感知业务逻辑类运行到哪里然后执行;
编写通知方法:
1. 前置通知(@Before):在目标方法运行之前运行;
2. 后置通知(@After):在目标方法运行结束之后运行(无论方法正常结束还是异常结束);
3. 返回通知(@AfterReturning):在目标方法正常返回之后运行;
4. 异常通知(@AfterThrowing):在目标方法出现异常以后运行;
5. 环绕通知(@Around):动态代理,手动推进目标方法运行(ProceedingJoinPoint.procced());
给切面类的目标方法标注何时何地运行(通知注解); 将切面类和业务逻辑类(目标方法所在类)都加入到容器中;
必须告诉Spring哪个类是切面类(给切面类上加一个注解:@Aspect
);
给配置类中加 @EnableAspectJAutoProxy
,开启基于注解的aop模式(很多以Enablexxx开头的注解均是开启对应某项功能)。
@Component("logger")
@Aspect//表示当前类是一个切面类
public class Logger {
// 抽取公共切入点表达式, impl下的任意类中、任意方法、任意参数
@Pointcut("execution(* io.github.tjtulong.service.impl.*.*(..))")
private void pt1(){
}
/**
* 前置通知
*/
//@Before("public int com.atguigu.aop.MathCalculator.div(int,int)")
@Before("pt1()")
public void beforePrintLog(JoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
//打印调用的方法名,以及方法中的参数列表
System.out.println("前置通知的"+joinPoint.getSignature.getName()+"方法开始记录日志了。参数列表:{"+Arrays.asList(args)+"}");
}
/**
* 后置通知
*/
// returning 用于标注接收返回值对象
// JoinPoint 要出现在参数的第一位,不能写在后面
@AfterReturning(value="pt1()", returning="result")
public void afterReturningPrintLog(JoinPoint joinPoint, Object result){
System.out.println("后置通知的"+joinPoint.getSignature.getName()+"方法开始记录日志了。返回结果为:"+result);
}
/**
* 异常通知
*/
@AfterThrowing(value="pt1()", throwing="exception")
public void afterThrowingPrintLog(Exception exception){
System.out.println("异常通知Logger类中的afterThrowingPrintLog方法开始记录日志了。异常信息为:{"+exception+"}");
}
/**
* 最终通知
*/
@After("pt1()")
public void afterPrintLog(){
System.out.println("最终通知Logger类中的afterPrintLog方法开始记录日志了。。。");
}
}
阅读Sring源码的核心是:看给容器中注册了什么组件,这个组件什么时候工作,这个组件的功能是什么。
@EnableAspectJAutoProxy
注解@EnableAspectJAutoProxy
的作用:
@Import(AspectJAutoProxyRegistrar.class)
:给容器中导入AspectJAutoProxyRegistrar
AspectJAutoProxyRegistrar
自定义给容器中注册bean;
AnnotationAwareAspectJAutoProxyCreator
, id为 internalAutoProxyCreator
@EnableAspectJAutoProxy
上的额外属性信息,进行必要的额外配置。@EnableAspectJAutoProxy
源码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
/**
* Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
* to standard Java interface-based proxies. The default is {@code false}.
*/
boolean proxyTargetClass() default false;
/**
* Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
* for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
* Off by default, i.e. no guarantees that {@code AopContext} access will work.
* @since 4.3.1
*/
boolean exposeProxy() default false;
}
AnnotationAwareAspectJAutoProxyCreator
组件AnnotationAwareAspectJAutoProxyCreator
类的层级结构图:
注意:实现了SmartInstantiationAwareBeanPostProcessor
与BeanFactoryAware
接口,说明该类为后置处理器(在bean初始化完成前后做事情)并自动装配了BeanFactory
。
AbstarctAutoProxyCreator.setBeanFactory();
AbstractAutoProxyCreator.后置处理器的逻辑
AbstractAdvisorAutoProxyCreator.setBeanFactory() -> initBeanFactory()
AnnotionationAwareAspectJAutoProxyCreator.initBeanFactory();
创建和注册AnnotationAwareAspectJAutoProxyCreator
的过程
step1:传入配置类,创建ioc容器;
step2:注册配置类,调用refresh()
刷新容器;
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses){
this();
register(annotatedClasses);
refresh();
}
step3:registerBeanPostProcessors(beanFactory)
,注册bean的后置处理器来方便拦截bean的创建;
BeanPostProcessor
BeanPostProcessor
PriorityOrdered
接口的BeanPostProcessor
;Ordered
接口的BeanPostProcessor
;BeanPostProcessor
;BeanPostProcessor
,实际上就是创建BeanPostProcessor
对象,保存在容器中;AnnotationAwareAspectJAutoProxyCreator
,创建一个id为internalAutoProxyCreator
的BeanPostProcessor
, 具体流程为:1. 通过createBean()创建Bean的实例;
2. populateBean():给bean的各种属性赋值;
3. initializeBean():初始化bean;
(1) invokeAwareMethods():处理Aware接口的方法回调(赋值)
(2) applyBeanPostProcessorsBeforeInitialization():执行所有后置处理器的postProcessBeforeInitialization()
(3) invokeInitMethods();执行自定义的初始化方法
(4) applyBeanPostProcessorsAfterInitialization():执行所有后置处理器的postProcessAfterInitialization()
//设置beanFactory,并initBeanFactory();
4. BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)创建成功;--> aspectJAdvisorsBuilder
beanFactory.addBeanPostProcessor(postProcessor);
以上是创建和注册AnnotationAwareAspectJAutoProxyCreator的过程
step4:finishBeanFactoryInitialization(beanFactory)
:完成BeanFactory初始化工作,创建剩下的单实例bean。
遍历获取容器中所有的Bean,依次创建对象getBean(beanName)
;
创建bean。AnnotationAwareAspectJAutoProxyCreator
在所有bean创建之前会有一个拦截,InstantiationAwareBeanPostProcessor
会调用postProcessBeforeInstantiation()
方法,其流程如下:
1. 先从缓存中获取当前bean,如果能获取到,说明bean是之前被创建过的,直接使用,否则再创建;只要创建好的Bean都会被缓存起来
2. createBean(),创建bean;
1) AnnotationAwareAspectJAutoProxyCreator会在任何bean创建之前先尝试返回bean的实例
【BeanPostProcessor是在Bean对象创建完成初始化前后调用的】
【InstantiationAwareBeanPostProcessor是在创建Bean实例之前先尝试用后置处理器返回对象的】
(a) resolveBeforeInstantiation(beanName, mbdToUse);解析BeforeInstantiation
希望后置处理器在此能返回一个代理对象;如果能返回代理对象就使用,如果不能就继续(b)
bean = applyBeanPostProcessorsBeforeInstantiation():
//拿到所有后置处理器,如果是InstantiationAwareBeanPostProcessor,就执行postProcessBeforeInstantiation
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
(b) doCreateBean(beanName, mbdToUse, args);真正的去创建一个bean实例,与step3中一致
AnnotationAwareAspectJAutoProxyCreator
【InstantiationAwareBeanPostProcessor
】的作用:
每一个bean创建之前,调用postProcessBeforeInstantiation()
;
创建对象 ----> postProcessAfterInitialization()
postProcessAfterInitialization()
return wrapIfNecessary(bean, beanName, cacheKey); //包装如果需要的情况下
1. 获取当前bean的所有增强器(通知方法) Object[] specificInterceptors
(1) 找到候选的所有的增强器(找哪些通知方法是需要切入当前bean方法的);
(2) 获取到能在bean使用的增强器;
(3) 给增强器排序.
2. 保存当前bean在advisedBeans中;
3. 如果当前bean需要增强,创建当前bean的代理对象;
(1) 获取所有增强器(通知方法)
(2) 保存到proxyFactory
(3) 创建代理对象:Spring自动决定
JdkDynamicAopProxy(config);jdk动态代理;
ObjenesisCglibAopProxy(config);cglib的动态代理;
4. 给容器中返回当前组件使用jdk/cglib增强了的代理对象;
5. 以后容器中获取到的就是这个组件的代理对象,执行目标方法的时候,代理对象就会执行通知方法的流程;
CglibAopProxy.intercept()
:拦截目标方法的执行
根据ProxyFactory对象获取将要执行的目标方法的拦截器链
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
...
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 重点:将所有的MethodInterceptor串成一个链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
//如果没有拦截器,直接执行目标方法
if(chain.isEmpty() && Modifier.isPublic(method.getModifiers())){
Object[] argsToUse = AopProxyUtils.adaptArgumentsInfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else{
// proxy为动态代理后的bean
// target为原bean
// proceed方法为处理之前提到的chain上所有methodInterceptor
// 最后一个methodinterceptor调用methodProxy的invoke方法
// methodProxy.invoke(this.target, this.arguments);
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
拦截器链的获取:
List
public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {
@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, Class<?> targetClass) {
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
for (Advisor advisor : config.getAdvisors()) {
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
//将所有的增强器,转为Interceptor;
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
...
}
@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
Advice advice = advisor.getAdvice();
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
}
List
保存所有的拦截器
遍历所有的拦截器,将其转为Interceptor;
registry.getInterceptors(advisor);
将增强器转为List
;
MethodInterceptor
,直接加入到集合中AdvisorAdapter
将增强器转为MethodInterceptor
MethodInterceptor
数组。如果没有拦截器执行目标方法,或者拦截器的索引和拦截器数组-1大小一样(指定到了最后一个拦截器),则执行目标方法;
链式获取每一个拦截器,拦截器执行invoke方法,每一个拦截器等待下一个拦截器执行完成返回以后再来执行;拦截器链的机制,保证通知方法与目标方法的执行顺序。
参考:https://www.jianshu.com/p/1b557d22fad3
@EnableTransactionManagement
@ComponentScan("top.tjtulong.tx")
@Configuration
public class TxConfig {
//数据源
@Bean
public DataSource dataSource() throws Exception{
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser("root");
dataSource.setPassword("123456");
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
return dataSource;
}
// 创建JdbcTemplate组件
@Bean
public JdbcTemplate jdbcTemplate() throws Exception{
//调用dataSource()方法时,Spring对@Configuration类会特殊处理;
//给容器中加组件的方法,多次调用都只是从容器中找组件
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource());
return jdbcTemplate;
}
//注册事务管理器在容器中
@Bean
public PlatformTransactionManager transactionManager() throws Exception{
return new DataSourceTransactionManager(dataSource());
}
}
环境搭建步骤:
1. 导入相关依赖:数据源、数据库驱动、Spring-jdbc模块
2. 配置数据源、 JdbcTemplate(Spring提供的简化数据库操作的工具)操作数据
3. 给方法上标注@Transactional 表示当前方法是一个事务方法
4. @EnableTransactionManagement 开启基于注解的事务管理功能
5. 配置事务管理器来控制事务 DataSourceTranscationManager()
@EnableTransactionManagement
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
/**
* Indicate whether subclass-based (CGLIB) proxies are to be created ({@code true}) as
* opposed to standard Java interface-based proxies ({@code false}). The default is
* {@code false}. Applicable only if {@link #mode()} is set to
* {@link AdviceMode#PROXY}.
* Note that setting this attribute to {@code true} will affect all
* Spring-managed beans requiring proxying, not just those marked with
* {@code @Transactional}. For example, other beans marked with Spring's
* {@code @Async} annotation will be upgraded to subclass proxying at the same
* time. This approach has no negative impact in practice unless one is explicitly
* expecting one type of proxy vs another, e.g. in tests.
*/
boolean proxyTargetClass() default false;
/**
* Indicate how transactional advice should be applied. The default is
* {@link AdviceMode#PROXY}.
* @see AdviceMode
*/
AdviceMode mode() default AdviceMode.PROXY;
/**
* Indicate the ordering of the execution of the transaction advisor
* when multiple advices are applied at a specific joinpoint.
* The default is {@link Ordered#LOWEST_PRECEDENCE}.
*/
int order() default Ordered.LOWEST_PRECEDENCE;
}
功能于@EnableAspectJAutoProxy
类似,利用TransactionManagementConfigurationSelector
给容器中导入两个组件:
AutoProxyRegistrar
InfrastructureAdvisorAutoProxyCreator
组件(也是一个后置处理器)2.ProxyTransactionManagementConfiguration
给容器中注册**事务增强器**;
1. 事务增强器要用事务注解的信息,`AnnotationTransactionAttributeSource` 解析事务注解。
2. 事务拦截器:`TransactionInterceptor`。 保存了事务属性信息,事务管理器;(本质上是一个 `MethodInterceptor`)。
在目标方法执行的时候,执行拦截器链,即事务拦截器:
1. 先获取事务相关属性,再获取`PlatformTranscationManager`。如果事先没有添加指定任何`transcationManager`,最终会从容器中按类型获取一个`PlatformTranscationManager`。
2. 执行目标方法时
- 如果异常,获取到事务管理器,利用事务管理回滚操作
- 如果正常,利用事务管理器,提交事务。
BeanFactory 的后置处理器。在BeanFactory 标准初始化之后调用,用来定制和修改BeanFactory的内容。
执行时机:所有的bean定义已经保存加载到beanFactory,但是bean的实例还未创建
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("MyBeanFactoryPostProcessor...postProcessBeanFactory...");
// 获取容器中组件的数量
int count = beanFactory.getBeanDefinitionCount();
// 获取容器中全部组件的名称
String[] names = beanFactory.getBeanDefinitionNames();
System.out.println("当前BeanFactory中有"+ count +" 个Bean");
System.out.println(Arrays.asList(names));
}
}
原理 :
ioc容器创建对象 refresh()
——> invokeBeanFactoryPostProcessors(beanFactory);
BeanFactoryPostPorcessor
的子接口 BeanDefinitionRegistryPostProcessor
继承于BeanFactoryPostProcessor,实现的方法为postProcessBeanDefinitionRegistry();
执行时机:在所有bean定义信息将要被加载,bean实例还未创建的;
优先于BeanFactoryPostProcessor 执行,利用BeanDefinitionRegistryPostProcessor
给容器中再额外添加一些组件;
示例代码
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor{
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("MyBeanDefinitionRegistryPostProcessor...bean的数量:"+beanFactory.getBeanDefinitionCount());
}
//BeanDefinitionRegistry为Bean定义信息的保存中心,以后BeanFactory就是按照 BeanDefinitionRegistry 里面保存的每一个bean定义信息创建bean实例;
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("postProcessBeanDefinitionRegistry...bean的数量:"+registry.getBeanDefinitionCount());
//RootBeanDefinition beanDefinition = new RootBeanDefinition(Blue.class);
// 手动添加一个BeanDefinition
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Blue.class).getBeanDefinition();
registry.registerBeanDefinition("hello", beanDefinition);
}
}
原理:
refresh()
——> invokeBeanFactoryPostProcessors(beanFactory)
;BeanDefinitionRegistryPostProcessor
组件;
postProcessBeanDefinitionRegistry()
方法;postProcessBeanFactory()
方法 (BeanFactoryPostProcessor
中定义);BeanFactoryPostProcessor
组件;然后依次触发postProcessBeanFactory()
方法。监听容器中发布的事件,事件驱动模型开发。
public interface ApplicationListener
监听ApplicationEvent 及其下面的子事件
@Component
public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {
//当容器中发布此事件以后,方法触发
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("收到事件:"+event);
}
}
步骤:
写一个监听器(ApplicationListener
实现类)来监听某个事件( ApplicationEvent
及其子类)也可以使用 @EventListener
把监听器加入容器中
只要容器中有相关事件的发布,我们就能监听这个事件
ContextRefreshedEvent
:容器刷新完成(所有bean都完全创建)会发布这个事件;ContextClosedEvent
:关闭容器会发布这个事件;也可以自己发布事件:applicationContext.publishEvent(object)
;
refresh()
--> registerListeners()
;
从容器中拿到所有的监听器,把他们注册到applicationEventMulticaster
中(注意此时并不初始化):
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for(String listenerBeanName : listenerBeanNames){
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
示例:ContextRefreshedEvent
事件,自己发布的事件,ContextClosedEvent
事件:
ContextRefreshedEvent
事件:
refresh()
;finishRefresh();
finshRefresh()
--> publishEvent(new ContextRefreshedEvent(this))
;
自己发布的事件
容器关闭事件 ContextClosedEvent
publishEvent(new ContextRefreshedEvent(this));
getApplicationEventMulticaster()
;multicastEvent()
派发事件;ApplicationListener
;public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
// 1.如果有Executor,可以支持使用Executor进行异步派发;
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(new Runnable() {
@Override
public void run() {
invokeListener(listener, event);
}
});
}
else {
// 2.否则,同步的方式直接执行listener方法;
invokeListener(listener, event);
//invokeListener()中将拿到listener并回调onApplicationEvent()方法;
}
}
}
刷新容器 refresh()
——> initApplicationEventMulticaster()
; 初始化ApplicationEventMulticaster
;
id="applicationEventMulticaster"
的组件;有则直接获取该组件this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory)
;并且加入到容器中,我们就可以在其他组件要派发事件,自动注入这个applicationEventMulticaster
。如何知道容器中有哪些监听器applicationListener
容器创建对象:refresh()
;
registerListeners()
protected void registerListeners() {
// Register statically specified listeners first.
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
//从容器中拿到所有的监听器,把它们注册到 applicationEventMulticaster中
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
//将listener注册到ApplicationEventMulticaster中
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// Publish early application events now that we finally have a multicaster...
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
@EventListener 注解的使用和原理
package com.atguigu.ext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.EventListenr;
import org.springframework.stereotype.Service;
@Service
public class UserService{
//指定监听什么事件
@EventListener(classes={
ApplicationEvent.class})
public void listen(ApplicationEvent event){
System.out.println("UserService..监听到的事件:" + event);
}
}
原理:
EventListenerMethodProcessor
处理器来解析方法上的 @EventListener
。EventListenerMethodProcessor
方法中实现了 SmarthInitializingSingleton
接口ioc 容器创建对象并 refresh()
finishBeanFactoryInitialization(beanFactory)
;初始化剩下的单实例bean;
SmartInitializingSingleton
类型的,如果是就调用 smartSIngleton.afterSingletonsInstantiated()
方法;(在所有单实例bean创建完成之后调用)(标准初始化工作)
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
...
prepareRefresh()
刷新前的预处理intiPropertySoruces()
初始化一些属性设置;主要是提供给子类自定义个性化的属性设置方法。getEnvironment().validateRequiredProperties()
:检验属性是否合法。earlyApplicationEvents = new LinkedHashSet()
; 保存容器中的一些早期事件。protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
// Initialize any placeholder property sources in the context environment
initPropertySources();
// Validate that all properties marked as required are resolvable
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}
obtainFreshBeanFactory()
:获取BeanFactory// 其中只包含默认的属性设置
refreshBeanFactory()
:刷新【创建】BeanFactory;this.beanFactory = new DefultListableBeanFactory()
;getBeanFactory()
返回刚才GenericApplicationContext
创建的BeanFactory。prepareBeanFactory
: BeanFactory 的预准备工作(BeanFactory 进行一些设置)
ApplicationContextAwareProceesor
】EnvironmentAware
,EmbeddedValueResolverAware
,...
;BeanFactory
, ResourceLoader
, ApplicationEventPulisher
, ApplicationContext
.BeanPostProcessor
【ApplicationListenerDetector
】ConfigurableEnvironment
】Map
】Map
】源码:
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
postProcessBeanFactory(beanFactory)
:BeanFactory准备工作完成后(标准初始化后)进行的后置处理工作。子类通过重写这个方法来在BeanFactory创建并预准备完成以后进行进一步的设置。
【以上为BeanFactory的创建及预准备工作(标准初始化工作)】
invokeBeanFactoryPostProcessor(beanFactory)
:执行BeanFactoryPostProcessor 的方法。BeanFactoryPostProcessor
、BeanDefinitionRegistryPostPorcessor
子接口执行 BeanFactoryPostProcessor
中的方法:
【需要先执行 BeanDefinitionRegistryPostProcessor
方法】
获取所有的BeanDefinitionRegistryPostProcessor
;
先执行实现了PriorityOrdered 优先级接口的BeanDefinitionRegistryPostProcessor
:
postProcessor.postProcessBeanDefinitionRegistry(registry)
再执行实现了Ordered顺序接口的 BeanDefinitionRegistryPostProcessor
:
postProcessor.postProcessBeanDefinitionRegistry(registry)
最后执行没有实现任何优先级的 BeanDefinitionRegistryPostProcessor(registry)
。
postProcessor.postProcessBeanDefinitionRegistry(registry)
【再执行 BeanFactoryPostProcessor
方法】
BeanFactoryPostPorcessor
;BeanFactoryPostPorcessor
;BeanFactoryPostPorcessor
;BeanFactoryPostPorcessor()
。postProcessor.postProcessBeanFactory()
registerBeanPostPorcessors(beanFactory)
: 注册BeanPostPorceesor(Bean 的后置处理器)【作用】:拦截Bean 的创建过程
不同接口类型的BeanPostPorcessor
,在Bean创建前后的获取时机不同。
需要创建的 BeanPostProcessor 包括:
1. DestructionAwareBeanPostProcessor
2. InstantiationAwareBeanPostProcessor
3. SmartInstantiationAwarePostPorcessor
4. MergeBeanDefinitionPostProcessor
获取所有的BeanPostProcessor;后置处理器默都可以通过PriorityOrdered / Oreder接口来执行优先执行时机。
先注册PriorityOrdered优先级接口的 BeanPostProcessor
;把每一个BeanPostProcessor 添加到BeanFactory中。
beanFactory.addBeanPostProcessor(postProcessor)
再注册Ordered接口的;
最后注册没有实现任何优先级接口的;
最终注册MergeBeanDefinitionPostProcessor
(因为属于internalBeanPostProcessor
)
注册一个 ApplicationListenerDetector
,在Bean创建完成后检查是否是ApplicationListener
:如果是,就放在:applicationContext.addApplicationListener((ApplicationLIistener>)bean);
initMessageSource()
; 初始化MessageSource
组件(做国际化功能;消息绑定;消息解析)
获取BeanFactory;
看容器中有id为messageSource
的,类实现是否MessageSource
的组件;
messageSource
;如果没有,自己创建一个DelegatingMessageSource
;MessageSource
: 去国际化配置文件中某个key的值,能按照区域信息获取把创建好的MessageSource
注册在容器中,以后获取国际化配置文件中的值的时候,可以自动注入MessageSource;
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME,this.messageSource);
MessageSource.getMessage(String code, Object[] args, String defaultMessage, Local local);
initApplicationEventMulticaster()
: 初始化事件派法器applicationEventMulticaster
的 ApplicationEventMulticaster
SimpleApplicationEventMulticaster
ApplicationEventMulticaster
添加到BeanFactory中,以后其他组件直接自动注入。onRefresh()
:留给子容器(子类重写onRefresh()方法)子类重写这个方法,子容器刷新时可以自定义逻辑
registerListeners()
: 将容器中所有项目里面的ApplicationListener注册进来从容器中拿到所有的 ApplicationListener
将每个监听器添加到事件派法器中
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName)
派发之前步骤产生的事件
finishBeanFactoryInitialization(beanFactory)
; 初始化所有剩下的单实例beanbeanFactory.preInstantiateSingletons()
: 初始化后剩下的单实例bean
a. 获取容器中所有Bean, 依次进行初始化和创建对象
b. 获取Bean的定义信息:RootBeanDefinition
c. 如果Bean 不是抽象的,是单例的,不是懒加载的
1. 判断是否是FactoryBean; 是否是实现FactoryBean接口的Bean
2. 不是工厂Bean,利用 getBean(beanName) 来创建Bean对象。
getBean()
方法原理getBean(beanName)
与 ioc.getBean()
相同.
doGetBean(name, null, null, false)
;
先获取缓存中保存的单实例Bean;如果能获取到说明该Bean已被创建过(所有创建过的单实例Bean都会被缓存起来)。
getSingleton()
从 singletonObjects 中获取。
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>();
缓存中获取不到,开始Bean的创建
标记当前bean被创建
获取bean的定义信息
获取当前Bean依赖的其他Bean;如果有,按照 getBean()
把依赖的Bean先创建出来
启动单实例Bean的创建流程
○ 所有Bean都利用 getBean()
创建完成以后; 检查所有的Bean是否是 SmartInitializingSingleton
接口的;如果是;就执行 afterSingletonsInstantiated()
方法。
createBean(beanName, mbd, args)
;
Object bean = resolveBeforeInstantiation(beanName, mbdTouse)
; 让BeanPostPorcessor
先拦截返回代理对象。
§
InstantiationAwareBeanPostProcessor
提前执行;
§ 先触发postProcessBeforInstantiation()
;
§ 如果有返回值,触发postProcessAfterInstantiation()
;
如果前面的 InstantitationAwareBeanPostProcessor
没有返回代理对象; 调用4
【 创建 Bean! 】Object beanInstance = doCreateBean(beanName, mbdToUse, args)
;
【创建Bean实例】:createBeanInstance(beanName, mbdToUse, args);
利用工厂方法或者对象的构造器来创建Bean实例。
【applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)
方法】;
调用 MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition(mbd, beanType, beanName)
;
【为Bean属性赋值】populateBean(beanName, mbd, instanceWrapper)
) 拿到InstantiationAwareBeanPostProcessor
后置处理器,调用postProcessAfterInstantiation()
;
) 拿到 InstantiationAwareBeanPostProcessor
后置处理器,调用 postProcessPropertyValues()
;
【以上是赋值之前】
applypropertyValues(beanName, mbd, bw,pvs)
;【 Bean初始化 】initalizeBean(beanName, exposedObject, mbd)
;
) 【执行Aware接口方法】invokdeAwareMethods(beanName, bean)
; 执行xxxAware接口方法;
BeanNameAware
\ BeanClassLoaderAware
\ BeanFactoryAware
接口
)【执行后置处理器初始化之前】 applyBeanPostProcessorsBeforInitialization(wrappedBean, beanName)
;
BeanPostPorcessor.postProcessBeforInitialization();
) 【执行初始化方法】invokeInitMethods(beanName, wrappedBean, mbd)
;
InitalizationBean
接口的实现, 执行接口规定的初始化) 【执行后置处理器初始化之后的方法】applyBeanPostProcessorsAfterInitialization
BeanPostProcessor.postProcessAfterInitialization();
) 注册Bean的销毁方法
将已经创建好的Bean添加到缓存 singletonObjects
中。
ioc容器就是这些Map组成;Map中保存了单实例Bean,环境信息等。
所有Bean都利用
getBean()
创建完成之后,检查所有的Bean是否是SmartInitializingSingleton
接口的;如果是,就执行afterSingletonsInstantiated()
方法。
finishRefresh()
完成BeanFactory的初始化创建工作; IOC容器就创建完成(initLifecycleProcessor()
--> getLifecycleProcessor()
--> publishEvent()
--> LiveBeansView
)
initLifecycleProcessor()
;初始化和生命周期有关的后置处理器;
)默认从容器中找是否有lifecycleProcessor
的组件LifecycleProcessor
,如果没有new DefaultLifecycleProcessor()
;同时加入到容器中;
)其中LifecycleProcessor
,运行写一个LifecycleProcessor
的实现类,可以在BeanFatory的
void onRefresh();
void onClose();
进行回调。
getLifecycleProcessor().onRefresh();
拿到前面定义的生命周期处理器(BeanFactory); 回调onRefresh()方法;
publishEvent( new ContextRefreshedEvent(this))
;发布容器刷新完成事件;
LiveBeansView.registerApplicationContext(this)
; ?
@Service
,@Component
,@Bean
getBean()
方法创建bean;创建好以后保存在容器中;finishBeanFactoryInitialization();
BeanPostProcessor
AutowiredAnnotationBeanPostProcessor
: 处理自动注入AnnotationAwareAspectJAutoProxyCreator
: 来做AOP功能;为bean创建代理对象,通过代理对象增强bean功能ApplicationListener
:事件监听;ApplicationEventMulticaster
: 事件派发;