1.@Autowired
标注在方法,Spring容器创建当前对象,就会调用方法,完成赋值;方法使用的参数,自定义类型的值从ioc容器中获取
自动装配;
Spring利用依赖注入(DI),完成对IOC容器中中各个组件的依赖关系赋值;
1)、@Autowired:自动注入:
A、默认优先按照类型去容器中找对应的组件:applicationContext.getBean(Person.class);找到就赋值
B、如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找applicationContext.getBean(“person”)
C、@Qualifier(“person”):使用@Qualifier指定组件的进行装配,不是属性名
D、自动装配默认一定要将属性赋值好,没有就会报错;可以使用@Autowired(required=false);
E、@Primary:让Spring进行自动装配的时候,默认使用首选的bean;
也可以继续使用@Qualifier指定需要装配的bean的名字
PersonService{
@Autowired
PersonDao personDao;
}
2)、Spring还支持使用@Resource(JSR250)和@Inject(JSR330)[java规范的注解]
@Resource:
可以和@Autowired一样实现自动装配功能;默认是按照组件名称进行装配的;
没有能支持@Primary功能
没有支持@Autowired(reqiured=false);
@Inject:
需要导入javax.inject的包,和Autowired的功能一样。没有required=false的功能;
@Autowired:Spring定义的; @Resource、@Inject都是java规范
AutowiredAnnotationBeanPostProcessor:解析完成自动装配功能;
3)、 @Autowired:可以使用在构造器,参数,方法,属性上;都是从容器中获取参数组件的值
A、[标注在方法位置]:@Bean+方法参数;参数从容器中获取;默认不写@Autowired效果是一样的;都能自动装配
B、[标在构造器上]:如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略,参数位置的组件还是可以自动从容器中获取
C、放在参数位置:
4)、自定义组件想要使用Spring容器底层的一些组件(ApplicationContext,BeanFactory,xxx);
自定义组件实现xxxAware;在创建对象的时候,会调用接口规定的方法注入相关组件;Aware;
把Spring底层一些组件注入到自定义的Bean中;
xxxAware:功能使用xxxProcessor;
ApplicationContextAware==》ApplicationContextAwareProcessor;
2.@Component
默认加在ioc容器中的组件,容器启动会调用无参构造器创建对象,再进行初始化赋值等操作【构造器要用的组件,都是从容器中获取】
3.@PostConstruct
对象初始化并赋值完成后调用
4.@PreDestroy
对象从容器中移除之前调用
5.@BeanPostProcessor
bean初始化前后执行的工作
6.@Value 给属性进行赋值
@Value(“A”) @Value(“${从配置文件中取值}”) @Vlaue(“#{SpEL表达式}”)
7.@ComponentScan
@ComponentScan value:指定要扫描的包
excludeFilters = Filter[] :指定扫描的时候按照什么规则排除那些组件
includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件【需要设置useDefaultFilters=false】
FilterType.ANNOTATION:按照注解
FilterType.ASSIGNABLE_TYPE:按照给定的类型;
FilterType.ASPECTJ:使用ASPECTJ表达式
FilterType.REGEX:使用正则指定
FilterType.CUSTOM:使用自定义规则
8.@Bean(“id值”)
给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id @Bean(“person”)
Bean注解的方法创建对象时的参数会从容器中获取。
9.@Import导入组件,id默认是组件的全类名
@Import({Color.class,Red.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
10.@Conditional({Human.class})
类中组件统一设置。满足当前条件,这个类中配置的所有bean注册才能生效;
给容器中注册组件;
1)、包扫描+组注注解:@Component @Controller @Service @Repository
2)、@Bean用于:导入的第三方包里面的组件
3)、@Import[快速给容器中导入一个组件]
1)、@Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名
2)、ImportSelector:返回需要导入的组件的全类名数组;
3)、ImportBeanDefinitionRegistrar:手动注册bean到容器中
4)、使用Spring提供的 FactoryBean(工厂Bean);
1)、默认获取到的是工厂bean调用getObject创建的对象
2)、要获取工厂Bean本身,我们需要给id前面加一个&&colorFactoryBean
11.@Scope(“prototype”)
@Lazy
@Bean(“person”)
public Person(){
return new Person();
}
@Scope 对象作用域
prototype:IOC容器启动并不会调用方法并放入容器中,而是每次需要时进行创建
singleton:单例、IOC容器启动后调用创建对象的方法,以后每次需要对象从容器中获取
ConfigurableBeanFactory#SCOPE_PROTOTYPE 多例
ConfigurableBeanFactory#SCOPE_SINGLETON 单例
org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST request 每次同一个request调用一次
org.springframework.web.context.WebApplicationContext#SCOPE_SESSION sesssion 每次同一个session调用一次
@Lazy :懒加载
若为单实例,则在容器启动后即创建对象
若为懒加载方式,则容器启动后不创建对象,需要时获取Bean创建对象并初始化
12.@Profile
Profile:Spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能;
开发环境、测试环境、生产环境;
数据源:(/A)(/B)(/C);
@Profile:指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件
1)、加了环境标识的bean,只有这个环境被激活的时候才能注册到容器中。默认是default环境
2)、写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生效
3)、没有标注环境标识的bean在,任何环境下都是加载的;
启用Profile起作用的方法有两种方式:
1.启动时添加参数 -Dspring.profile.actice=”指定的参数”
2.在代码中指定
//1、创建一个applicationContext
AnnotationConfigApplicationContext applicationContext =new AnnotationConfigApplicationContext();
//2、设置需要激活的环境
applicationContext.getEnvironment().setActiveProfiles("指定的参数");
//3、注册主配置类
applicationContext.register(MyConfigOfProfile.class);
//4、启动刷新容器
applicationContext.refresh();
class MyConfigOfProfileimplements EmbeddedValueResolverAware{
@Override
}
13.@PropertySource
使用@PropertySource读取外部配置文件中的k/v保存到运行的环境变量中;加载完外部的配置文件以后使用${}取出配置文件的值
@PropertySource(value={“classpath:/db.properties”})
12.Bean的生命周期
bean的生命周期:
bean创建—-初始化——销毁的过程
容器管理bean的生命周期;
我们可以自定义初始化和销毁方法;容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法
构造(对象创建)
单实例:在容器启动的时候创建对象
多实例:在每次获取的时候创建对象
BeanPostProcessor.postProcessBeforeInitialization
初始化:
对象创建完成,并赋值好,调用初始化方法。。。
BeanPostProcessor.postProcessAfterInitialization
销毁:
单实例:容器关闭的时候
多实例:容器不会管理这个bean;容器不会调用销毁方法;
遍历得到容器中所有的BeanPostProcessor;挨个执行beforeInitialization,
一但返回null,跳出for循环,不会执行后面的BeanPostProcessor.postProcessorsBeforeInitialization
BeanPostProcessor原理
populateBean(beanName, mbd, instanceWrapper);给bean进行属性赋值
initializeBean 初始化Bean
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
invokeInitMethods(beanName, wrappedBean, mbd);执行自定义初始化
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
<1> 通过@Bean(initMethod=””,destoryMethod=””)
<2> 通过Bean实现InitiallizingBean与DisposableBean实现bean的初始化和销毁
<3> 使用JSR250定义的方式
@PostConstruct:在bean创建完成并且属性赋值完成后执行初始化方法
@PreDestroy:在容器销毁bean之前进行清理工作
<4> 实现BeanPostProcessor接口的后置处理器方法
postProcessBeforeInitialization:初始化之前处理
postProcessAfterInitialization:初始化之后处理
Spring底层对 BeanPostProcessor 的使用;
bean赋值,注入其他组件,@Autowired,生命周期注解功能,@Async,xxx BeanPostProcessor;
13.AOP 【动态代理】 @EnableAspectJAutoProxy
指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式;
1、导入aop模块;Spring AOP:(spring-aspects)
2、定义一个业务逻辑类(MathCalculator);在业务逻辑运行的时候将日志进行打印(方法之前、方法运行结束、方法出现异常,xxx)
3、定义一个日志切面类(LogAspects):切面类里面的方法需要动态感知MathCalculator.div运行到哪里然后执行;
通知方法:
前置通知(@Before):logStart:在目标方法(div)运行之前运行
后置通知(@After):logEnd:在目标方法(div)运行结束之后运行(无论方法正常结束还是异常结束)
返回通知(@AfterReturning):logReturn:在目标方法(div)正常返回之后运行
异常通知(@AfterThrowing):logException:在目标方法(div)出现异常以后运行
环绕通知(@Around):动态代理,手动推进目标方法运行(joinPoint.procced())
4、给切面类的目标方法标注何时何地运行(通知注解);
5、将切面类和业务逻辑类(目标方法所在类)都加入到容器中;
6、必须告诉Spring哪个类是切面类(给切面类上加一个注解:@Aspect)
7、给配置类中加 @EnableAspectJAutoProxy 【开启基于注解的aop模式】
在Spring中很多的 @EnableXXX;
三步:
1)、将业务逻辑组件和切面类都加入到容器中;告诉Spring哪个是切面类(@Aspect)
2)、在切面类上的每一个通知方法上标注通知注解,告诉Spring何时何地运行(切入点表达式)
3)、开启基于注解的aop模式;@EnableAspectJAutoProxy
AOP原理:【看给容器中注册了什么组件,这个组件什么时候工作,这个组件的功能是什么?】
@EnableAspectJAutoProxy;
1、@EnableAspectJAutoProxy是什么?
@Import(AspectJAutoProxyRegistrar.class):给容器中导入AspectJAutoProxyRegistrar
利用AspectJAutoProxyRegistrar自定义给容器中注册bean;BeanDefinetion
internalAutoProxyCreator=AnnotationAwareAspectJAutoProxyCreator,给容器中注册一个AnnotationAwareAspectJAutoProxyCreator;
2、 AnnotationAwareAspectJAutoProxyCreator:
AnnotationAwareAspectJAutoProxyCreator
->AspectJAwareAdvisorAutoProxyCreator
->AbstractAdvisorAutoProxyCreator
->AbstractAutoProxyCreator
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
关注后置处理器(在bean初始化完成前后做事情)、自动装配BeanFactory
AbstractAutoProxyCreator.setBeanFactory()
AbstractAutoProxyCreator.有后置处理器的逻辑;
AbstractAdvisorAutoProxyCreator.setBeanFactory()-》initBeanFactory()
AnnotationAwareAspectJAutoProxyCreator.initBeanFactory()
流程:
1)、传入配置类,创建ioc容器
2)、注册配置类,调用refresh()刷新容器;
3)、registerBeanPostProcessors(beanFactory);注册bean的后置处理器来方便拦截bean的创建;
1)、先获取ioc容器已经定义了的需要创建对象的所有BeanPostProcessor
2)、给容器中加别的BeanPostProcessor
3)、优先注册实现了PriorityOrdered接口的BeanPostProcessor;
4)、再给容器中注册实现了Ordered接口的BeanPostProcessor;
5)、注册没实现优先级接口的BeanPostProcessor;
6)、注册BeanPostProcessor,实际上就是创建BeanPostProcessor对象,保存在容器中;
创建internalAutoProxyCreator的BeanPostProcessor【AnnotationAwareAspectJAutoProxyCreator】
1)、创建Bean的实例
2)、populateBean;给bean的各种属性赋值
3)、initializeBean:初始化bean;
1)、invokeAwareMethods():处理Aware接口的方法回调
2)、applyBeanPostProcessorsBeforeInitialization():应用后置处理器的postProcessBeforeInitialization()
3)、invokeInitMethods();执行自定义的初始化方法
4)、applyBeanPostProcessorsAfterInitialization();执行后置处理器的postProcessAfterInitialization();
4)、BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)创建成功;—》aspectJAdvisorsBuilder
1)、把BeanPostProcessor注册到BeanFactory中;
beanFactory.addBeanPostProcessor(postProcessor);
=======以上是创建和注册AnnotationAwareAspectJAutoProxyCreator的过程========
AnnotationAwareAspectJAutoProxyCreator => InstantiationAwareBeanPostProcessor
4)、finishBeanFactoryInitialization(beanFactory);完成BeanFactory初始化工作;创建剩下的单实例bean
1)、遍历获取容器中所有的Bean,依次创建对象getBean(beanName);
getBean->doGetBean()->getSingleton()->
2)、创建bean
【AnnotationAwareAspectJAutoProxyCreator在所有bean创建之前会有一个拦截,InstantiationAwareBeanPostProcessor,会调用postProcessBeforeInstantiation()】
1)、先从缓存中获取当前bean,如果能获取到,说明bean是之前被创建过的,直接使用,否则再创建;只要创建好的Bean都会被缓存起来
2)、createBean();创建bean;
AnnotationAwareAspectJAutoProxyCreator 会在任何bean创建之前先尝试返回bean的实例
【BeanPostProcessor是在Bean对象创建完成初始化前后调用的】
【InstantiationAwareBeanPostProcessor是在创建Bean实例之前先尝试用后置处理器返回对象的】
1)、resolveBeforeInstantiation(beanName, mbdToUse);解析BeforeInstantiation
希望后置处理器在此能返回一个代理对象;如果能返回代理对象就使用,如果不能就继续
1)、后置处理器先尝试返回对象;
bean = applyBeanPostProcessorsBeforeInstantiation():
拿到所有后置处理器,如果是InstantiationAwareBeanPostProcessor;
就执行postProcessBeforeInstantiation
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
2)、doCreateBean(beanName, mbdToUse, args);真正的去创建一个bean实例;和3.6流程一样;
AnnotationAwareAspectJAutoProxyCreator【InstantiationAwareBeanPostProcessor】 的作用:
1)、每一个bean创建之前,调用postProcessBeforeInstantiation();
关心MathCalculator和LogAspect的创建
1)、判断当前bean是否在advisedBeans中(保存了所有需要增强bean)
2)、判断当前bean是否是基础类型的Advice、Pointcut、Advisor、AopInfrastructureBean,或者是否是切面(@Aspect)
3)、是否需要跳过
1)、获取候选的增强器(切面里面的通知方法)【List candidateAdvisors】
每一个封装的通知方法的增强器是 InstantiationModelAwarePointcutAdvisor;
判断每一个增强器是否是 AspectJPointcutAdvisor 类型的;返回true
2)、永远返回false
2)、创建对象
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)、给容器中返回当前组件使用cglib增强了的代理对象;
5)、以后容器中获取到的就是这个组件的代理对象,执行目标方法的时候,代理对象就会执行通知方法的流程;
3)、目标方法执行;
容器中保存了组件的代理对象(cglib增强后的对象),这个对象里面保存了详细信息(比如增强器,目标对象,xxx);
1)、CglibAopProxy.intercept();拦截目标方法的执行
2)、根据ProxyFactory对象获取将要执行的目标方法拦截器链;
List