1、spring 基于xml实现ApplicationContext的常用容器
1、FileSystemXmlApplicationContext 从文件系统加载配置
2、ClassPathXmlApplicationContext 从classpath加载配置
3、XmlWebApplicationContext 用于web应用程序的容器
2、spring 基于注解实现ApplicationContext的常用容器
1、AnnotationConfigServletWebServerApplicationContext
2、AnnotationConfigReactiveWebServerApplicationContext
3、AnnotationConfigApplicationContext
3、spring中的一级,二级、三级缓存对象
/** 1. 一级缓存对象singletonObjects 单例对象的缓存:bean名称到bean实例*/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** 2.二级缓存对象earlySingletonObjects 早期单例对象的缓存:bean名称到bean实例*/
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
/** 3.三级缓存对象singletonFactories 单例工厂的缓存:bean name到ObjectFactory*/
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
一级缓存对象存储的完整的bean实例(大部分获取bean实例中都是从一级缓存对象中获取)
二级缓存对象存储的是还没有注入属性的bean
三级缓存对象存储的是bean工厂对象(为了解决循环依赖而是用三级缓存对象)
spring框架是怎么解决循环依赖的呢(spring只支持单例的循环依赖)
A->B B->A 在实际工作中,我们很多时候会出现这个情况,A对象中依赖B对象 B对象中又依赖A对象 那么spring框架是怎么解决循环依赖的呢?
spring的Bean实例化和属性赋值是分开两步来做的,A对象实例化之后,属性注入之前,其实会把A对象放入三级缓存中,在实例化B对象,B对象中的A属性会从三级缓存中获取实例化对象
4、spring ioc理解
ioc及控制反转,那么ioc控制了什么?反转了什么?
- 什么是控制?那实际spring又是控制了什么?
(1)控制是指spring对bena的管理,及控制创建的对象,控制对象内属性的赋值 - 什么是反转?又是谁来进行反转的呢?
(1)反转是指创建对象的控制权交给ioc容器来控制(表示一种对象控制权的转移)
(2)有spring ioc容器进行反转 - 为什么要反转?反转之前有什么问题?反转之后有什么好处?
(1)没有反转则会添加代码的复杂度,代码量增多
(2)反转之后会把一系列创建对象的操作交给spring管理,spring创建,这样可以减少代码量
5、什么是BeanDefinition bean的定义
6、Bean的五大作用域
- singleton:spring的默认作用域,容器里拥有唯一的bean实例
- prototype:针对每个getBean请求,容器都会创建一个bean实例
- request:会为每个http请求创建一个bean实例
- session:会为每个session创建一个bean实例
- globalSession:会为每个全局http session创建一个bean实例,该作用域仅对portle有效
7、spring aop切面编程
aop的三种织入方式
- 编译时织入:需要特殊的java编译器,如AspectJ
- 类加载市织入:需要特殊的java编译器,如AspectJ和AspectWerkz
- 运行时织入:spring采用的方式,通过动态代理的方式,实现简单
/**
* @Aspect 标记为切面类 在包com.llp.o2o.web中所有的方法都进行前置和后置增强
*
*/
@Aspect
@Component
public class RequestLogAspect
{
private static final Logger logger = LoggerFactory.getLogger(RequestLogAspect.class);
//定义切入的位置
@Pointcut("execution(public * com.llp.o2o.web..*.*(..))")
public void webLog()
{
}
//方法执行前
@Before("webLog()")
public void doBefore(JoinPoint joinPoint)
{
// 接收到请求,记录请求内容
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 记录下请求内容
logger.info("URL : " + request.getRequestURL().toString());
logger.info("IP : " + request.getRemoteAddr());
}
//return返回之后进行切入 ret就是返回值
@AfterReturning(returning = "ret", pointcut = "webLog()")
public void doAfterReturning(Object ret)
{
// 处理完请求,返回内容
logger.info("RESPONSE : " + ret);
}
}
8、spring bean创建的生命周期(大概步骤)
- 推断构造方法 创建bean
(1)如果没有显示的写出任何构造器,则java默认使用无参的构造器
(2)如果显示的写出无参的构造器,则java使用无参的构造器
(3)如果显示的写出有参构造器且没有写出无参构造器,则java使用有参的构造器
(4)如果显示的写出两个有参构造器且没有写出无参构造器,则java无法默认选怎构造器,需要使用autowired注解进行指定选择 - 实例化bean
- 属性赋值,就是依赖注入
- 处理aware接口回调
- 初始化
(1)初始化前,处理@PostConstruct注解
(2)初始化,如果实现了InitializingBean接口spring容器会在属性赋值完成后调用afterPropertiesSet()方法
(3)初始化后,进行aop代理 - 销毁 调用 destroy()方法