spring日常问题
sofa中 context:property-placeholder 不生效,spring 版本为 5.1.14
BeanDefinition扫描器总结
BeanPostProcessor 总结
内部的BeanPostProcessor接口总结
内部的BeanPostProcessor实现总结
接触到的扩展点
- BeanFactoryPostProcessor 可以在 bean 正式初始化之前改变其值,该对象会被提前初始化;什么场景下?注意事项?
- BeanPostProcessor bean 的生命周期中,可用于所有的 bean;如 @PostConstruct 注解。
- FactoryBean 创建bean时(MethodLocatingFactoryBean);什么场景下?注意事项?
ioc
ioc概述
- IOC 总体来说有两处地方最重要,一个是创建 Bean 容器,一个是初始化 Bean
- ApplicationContext 继承自 BeanFactory,但是它不应该被理解为 BeanFactory 的实现类,
而是说其内部持有一个实例化的 DefaultListableBeanFactory。以后所有的 BeanFactory 相关的操作其实是委托给这个实例来处理的。 - BeanDefinition 解析/加载、注册 ;// 我们把这步叫做 注册Bean 吧
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); Bean 的生命周期:创建、装填属性、回调 各种初始化函数(init-method,InitializingBean,BeanPostProcessor)
ioc总的流程
ApplicationContext context = new ClassPathXmlApplicationContext(“classpath:applicationfile.xml”);
AbstractApplicationContext # refresh()
1 | public void refresh() throws BeansException, IllegalStateException { |
一些重要的类
AbstractRefreshableApplicationContext –> ResourceLoader,ApplicationEventPublisher,MessageSource
DefaultListableBeanFactory –> BeanDefinitionRegistry
AbstractAutowireCapableBeanFactory –主要为了 @Autowired 注解注入属性值
AnnotationConfigRegistry –ApplicationContext 基于注解配置的接口
beanDefinitionNames 一个 ArrayList, 可以看到从前到后加载的 beanname
InstantiationAwareBeanPostProcessor
- AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation
中调用了 ibp.postProcessBeforeInstantiation
在这里用体现了此接口用于初始化自定义的bean,主要是在Spring内部使用(自定义了 TargetSource 时)。 - AbstractAutowireCapableBeanFactory#populateBean
中调用了 ibp.postProcessAfterInstantiation,没找到有实际的使用 - 一个重要的实现 AutowiredAnnotationBeanPostProcessor
对采用 @Autowired、@Value 注解的依赖进行设值
allowCircularReferences
spring到底支持哪样子 的循环依赖(循环引用)??? 答案:单例的 setter 属性方式依赖
构造器 的循环依赖;DependsOn 的循环依赖 都无法解决。
AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues//这里 递归设置属性
DefaultSingletonBeanRegistry#getSingleton(java.lang.String)//这里进入 提前引用的返回
isSingletonCurrentlyInCreation():判断当前 singleton bean 是否处于创建中;
singletonObjects;//一级缓存,返回完整可用的 单例
earlySingletonObjects;//二级缓存,返回提前创建的 单例
singletonFactories;//三级缓存,为提前创建的 bean 加入 AbstractAutowireCapableBeanFactory#getEarlyBeanReference 逻辑(aop 的扩展?)
原理:对象的属性由 spring 容器统一设置,所以可以解决循环引用问题。
aop
spring 1.2
proxy 的配置方式
- 配置 bean
- 配置 Advice –指定执行前/执行后,处理逻辑
- 指定 Advisor –配置指定方法用指定 Advice 增强
- 指定 Interceptor –一般的 MethodInterceptor,写处理逻辑
- 配置 Proxy –配置指定的 bean 用指定的 interceptorNames 属性增强
- interceptorNames 可以指定为 Advice、Advisor、Interceptor 等
缺点:我们得为每个 bean 都配置一个代理,之后获取 bean 的时候需要获取这个代理类的 bean 实例(如 (UserService) context.getBean(“userServiceProxy”))
autoproxy 的配置方式
- 配置 bean
- 配置 Advice
- 配置 NameMatchMethodPointcutAdvisor, RegexpMethodPointcutAdvisor
- 配置 BeanNameAutoProxyCreator, DefaultAdvisorAutoProxyCreator
Advisor 有一个更加灵活的实现类 RegexpMethodPointcutAdvisor,它能实现正则匹配 指定方法增强
BeanNameAutoProxyCreator 是自己匹配方法,然后交由内部配置 advice 来拦截处理;
而 DefaultAdvisorAutoProxyCreator 是让 ioc 容器中的所有 advisor 来匹配方法,advisor 内部都是有 advice 的,让它们内部的 advice 来执行拦截处理。
proxy 与 autoproxy 比较
autoproxy 强调自动,也就是说 Spring 会自动做这件事,而不用像前面介绍的,我们需要显式地指定代理类的 bean。
Spring 2.0
@AspectJ 的配置方式
@AspectJ 和 AspectJ 没多大关系,并不是说基于 AspectJ 实现的,而仅仅是使用了 AspectJ 中的概念,包括使用了 AspectJ 的注解。
- 开启 @AspectJ 的注解配置方式(@EnableAspectJAutoProxy)
- 配置 @Aspect,切面类,包含以下两点:
- 配置 Pointcut 用于定义哪些方法需要被增强或者说需要被拦截
- 配置 Advice ,JoinPoint用于获取方法入参
Schema-based 的配置方式
示例如下:
1 | <aop:config> |
aop 命名空间的解析类:AopNamespaceHandler。
- 静态代理、动态代理的本质区别:代理对象创建时机不同,动态代理在调用时创建
- Spring AOP 的原理很简单,就是动态代理,它和 AspectJ 不一样,AspectJ 是直接修改掉你的字节码。
- 如果被代理的目标类实现了一个或多个自定义的接口,那么就会使用 JDK 动态代理,如果没有实现任何接口,会使用 CGLIB 实现代理,如果设置了 proxy-target-class=”true”,那么都会使用 CGLIB。
- InvocationHandler 只有一个方法,当生成的代理类对外提供服务的时候,都会导到这个方法中
aop 的实现
DefaultAdvisorAutoProxyCreator,…,AspectJAwareAdvisorAutoProxyCreator,AnnotationAwareAspectJAutoProxyCreator
AbstractAutoProxyCreator#postProcessAfterInitialization
入口在 AbstractAutowireCapableBeanFactory#initializeBean#applyBeanPostProcessorsAfterInitialization
spring 其他
典型的设计模式
- 策略模式
- 代理生成的两种方式:jdk 代理;cglib 代理
- 不同的资源加载方式,Resource 的设计思想
- 模板方法 AbstractHandlerMapping 的设计思想
- 观察者 事件设计
- 代理模式
- 装饰器模式 EncodedResource
- 访问者模式 ReflectionUtils
策略模式 与 模板方法 的区别
模板方法 侧重于继承结构,父类定义模板(或流程),子类重写指定方法;
策略模式 侧重于环境中的变化条件,根据不同的条件选择对应的策略。
使用到的容器
spring 中的 java 基础知识
- 反射-以一种更加通用的方式间接地操作目标类(相对于一般的调用)
- 动态代理(代理实例-相对一般的实例;一般用于横向逻辑)
- JDK动态代理(有接口的场景)
- InvocationHandler,可以通过实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态将横切逻辑和业务逻辑编织在一起。
- Proxy 利用 InvocationHandler 动态创建一个符合某一接口的实例,生成目标类的代理对象。
- PropertyEditor
JavaBean 规范通过 java.beans.PropertyEditor 定义了设置 JavaBean 属性的方法,通过 BeanInfo 描述了 JavaBean 哪些属性是可定制的,
此外还描述了可定制属性与 PropertyEditor 的对应关系。(属性描述器 PropertyDescriptor 为 JavaBean 属性指定编辑器)
PropertyEditorRegistrySupport -Spring 为常见的属性类型提供了默认的属性编辑器。
ConversionService,它提供了更为强大的类型转换的能力,可以完成任意类型之间的转换,还可以在转换过程中参考目标对象所在宿主类的上下文信息。 - XML基础知识
- 默认命名空间:它没有空间名,用于 Spring Bean 的定义;
- xsi 命名空间:这个命名空间用于为每个文档中命名空间指定相应的 Schema 样式文件,是标准组织定义的标准命名空间;
- aop 命名空间:这个命名空间是Spring配置AOP的命名空间,是用户自定义的命名空间。
- 命名空间的定义分为两个步骤:第一步指定命名空间的名称,第二步指定命名空间的 Schema 文档样式文件的位置,用空格或回车换行进行分隔。
- 注解-Java 语言解释器会忽略这些注解,而由第三方工具负责对注解进行处理。
- ThreadLocal
思路浅析:在 ThreadLocal 类中有一个 Map,用于存储每一个线程的变量副本,Map 中元素的键为线程对象,而值对应线程的变量副本。
在管理request作用域的Bean、事务管理、任务调度、AOP等模块都出现了它的身影(ThreadLocal)。 - 国际化信息
Java通过 java.util.Locale 类表示一个本地化对象,它允许通过语言参数和国家/地区参数创建一个确定的本地化对象。
支持多国语言的Web应用程序 == 多种资源文件(<资源名>_<语言代码>_<国家/地区代码>.properties)
spring 中,国际化信息资源应该是容器级。 - HTTP 报文
HTTP 请求报文由3部分组成(请求行+请求头+请求体)。 - @Value 注解
目前Spring的注解不支持静态的变量和方法,至于原因:有人说是因为Spring是基于对象层面的依赖注入的,而且使用静态的变量或类什么的话,扩大了其生命周期,给Testing带来困难,故Spring不推荐这样做。
spring in action
常用应用上下文:
- AnnotationConfigApplicationContext 基于 java 配置类中加载 spring 应用上下文
- ClassPathXmlApplicationContext 基于类路径下的 xml 文件中加载 spring 应用上下文
bean 的生命周期
实例化、填充属性、调用 XXXAware 接口、调用 postProcessBeforeInitialization()、调用 InitializingBean 接口、调用自定义初始化方法、调用 postProcessAfterInitialization()、创建完成使用、销毁 bean 对象、、、
spring 从两个角度来实现自动化装配
- 组件扫描(component scanning):spring 会自动发现应用上下文中所创建的 bean。
- 自动装配(autowiring):spring 自动满足 bean 之间的依赖。
- @Component –注解申明组件。
通过 Java 代码装配 bean
@Configuration 和 @Bean 的组合使用,但也少不了要开启组件扫描功能。
导入和混合配置
在 JavaConfig 中引用 XML 配置
@Configuration
@Import(MyJavaConfig.class)
@ImportResource(“classpath:WEB-INF/spring-context.xml”)
在 XML 中引用 JavaConfig 配置
1 | <bean class="org.poprabbit.smvcdemo.config.MyJavaConfig"/> |