spring 依赖注入的方式
- set方式
单例可以解决循环依赖问题
<bean class="com.Car" id="car" >
<property name="name" value="byd"></property>
</bean>
- 构造器方式
无需写大量的set, get方法
<bean class="com.Car" id="car" >
<constructor-arg value="byd"></constructor-arg>
</bean>
注解装配在 Spring 中是默认关闭的。所以需要在 Spring 文件中配置一下才能使用基于注解的装配模式
<beans>
<!--使用spring注解声明 -->
<context:annotation-config/>
<!--使用mvc注解声明 -->
<mvc:annotation-driven/>
</beans>
Spring 框架中的单例 Beans 是线程安全的么?
Spring 框架单例 bean 不是线程安全的,如果你的 bean 有多种状态的话(比如View Model对象),就需要自行保证线程安全,
但实际上,大部分的 bean 并没有可变的状态,所以在某种程度上说 Spring 的单例 bean 是线程安全的。
最浅显的解决办法就是将多态 bean 的作用域由“singleton”变更为“prototype”。
一、在什么情况下,单例的Bean对象存在线程安全问题
当Bean对象对应的类存在可变的成员变量并且其中存在改变这个变量的线程时,多线程操作该Bean对象时会出现线程安全。
二、原因
当多线程中存在线程改变了bean对象的可变成员变量时,其他线程无法访问该bean对象的初始状态,从而造成数据错乱
三、解决办法
1.在Bean对象中尽量避免定义可变的成员变量;
2.在bean对象中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在ThreadLocal中
简述 AOP 和 IOC 概念
AOP:Aspect Oriented Program, 面向(方面)切面的编程;Filter(过滤器) 也是一种 AOP.
AOP 是一种新的方法论, 是对传统 OOP(Object-Oriented Programming, 面向对象编程) 的补充.
AOP 的主要编程对象是切面(aspect), 而切面模块化横切关注点.可以举例通过事务说明.
IOC: Invert Of Control, 控制反转. 也成为 DI(依赖注入)其思想是反转资源获取的方向. 传统的资源查找方式要求组件向容器发起请求查找资源.作为回应, 容器适时的返回资源. 而应用了IOC 之后, 则是容器主动地将资源推送给它所管理的组件,组件所要做的仅是选择一种合适的方式来接受资源. 这种行为也被称为查找的被动形式
IOC 容器对 Bean 的生命周期:
①. 通过构造器或工厂方法创建 Bean 实例
②. 为 Bean 的属性设置值和对其他 Bean 的引用
③ . 将 Bean 实 例 传 递 给 Bean 后 置 处 理 器 的 postProcessBeforeInitialization 方法
④. 调用 Bean 的初始化方法(init-method)
⑤ . 将 Bean 实 例 传 递 给 Bean 后 置 处 理 器 的 postProcessAfterInitialization 方法
⑦. Bean 可以使用了
⑧. 当容器关闭时, 调用 Bean 的销毁方法(destroy-method)
修改bean信息
方法:实现BeanDefinitionRegistryPostProcessor 重写postProcessBeanFactory方法
@Component
public class MyBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 获得bean定义
RootBeanDefinition car = (RootBeanDefinition) beanFactory.getBeanDefinition("car");
// car.setBeanClassName("tank");
// 修改Class
// car.setBeanClass(Tank.class);
// 设置默认值 相当于xml:<property name="name" value="ls"/>
// car.getPropertyValues().addPropertyValue(new PropertyValue("name","ls"));
// 设置构造函数 相当于xml:<constructor-arg index="0" value="car2"/>
// car.getConstructorArgumentValues().addIndexedArgumentValue(0,"car2");
// 自动装配方式
//car.setAutowireMode(AUTOWIRE_BY_NAME);
// 强制依赖检查:
// car.setDependencyCheck(AbstractBeanDefinition.DEPENDENCY_CHECK_ALL);
//car.setInitMethodName("initMethod");
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
RootBeanDefinition beanDefinition=new RootBeanDefinition();
beanDefinition.setBeanClass(Tank.class);
registry.registerBeanDefinition("car",beanDefinition);
}
}
factoryBean
ioc.getBean(“car”)// 获得被Factory修饰后的getobject返回的对象
ioc.getBean("&car")//获得Bean本身
createBean方法中实现InstantiationAwareBeanPostProcessor 中止Bean的创建,返回bean后置处理器创建的Bean
调用bean工厂的后置处理器
1)BeanDefinitionRegistryPostProcessor(bean定义解析前调用):所有的bean定义信息将要被加载到容器中,Bean实例还没有被初始化
- 实现了PriorityOrdered接口的
- 实现了Ordered接口的
- 没有实现任何的优先级接口的
2)BeanFactoryPostProcessor(bean定义解析后调用):所有的Bean定义信息已经加载到容器中,但是Bean实例还没有被初始化.
- 实现了PriorityOrdered接口的
- 实现了Ordered接口的
- 没有实现任何的优先级接口的
//todo 第1个bean后置处理器
AbstractAutowireCapableBeanFactory
InstantiationAwareBeanPostProcessor
postProcessBeforeInstantiation
//todo 第2个bean后置处理器
AbstractAutowireCapableBeanFactory
SmartInstantiationAwareBeanPostProcessor
determineCandidateConstructors
//todo 第3个bean后置处理器
AbstractAutowireCapableBeanFactory
MergedBeanDefinitionPostProcessor
postProcessMergedBeanDefinition
//todo 第4个bean后置处理器
AbstractAutowireCapableBeanFactory
SmartInstantiationAwareBeanPostProcessor
getEarlyBeanReference
//todo 第5个bean后置处理器
AbstractAutowireCapableBeanFactory
InstantiationAwareBeanPostProcessor
postProcessAfterInstantiation
//todo 第6个bean后置处理器
AbstractAutowireCapableBeanFactory
InstantiationAwareBeanPostProcessor
postProcessPropertyValues
//todo 第7个bean后置处理器
AbstractAutowireCapableBeanFactory
BeanPostProcessor
postProcessBeforeInitialization
//todo 第8个bean后置处理器
AbstractAutowireCapableBeanFactory
BeanPostProcessor
postProcessAfterInitialization
//todo 第9个bean后置处理器
AbstractBeanFactory
DestructionAwareBeanPostProcessors
requiresDestruction
spring 集成mybatis mapper是接口需要重写这个类
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
AnnotationMetadata metadata = beanDefinition.getMetadata();
// metadata.isIndependent()=顶级类、嵌套类、静态内部类
// metadata.isConcrete() =非接口、非抽象类
// metadata.isAbstract() && metadata.hasAnnotatedMethods(Lookup.class.getName() = 抽象类并且必须方法中有@LookUp
return (metadata.isIndependent() && (metadata.isConcrete() ||
(metadata.isAbstract() && metadata.hasAnnotatedMethods(Lookup.class.getName()))));
}