1.手动注入:通过XML进行配置bean属性
1.1Set方法
可以通过ByType,ByName进行赋值
1.2.构造方法注入
2.自动注入
2.1通过XML自动注入【set和构造方法】
2.2通过@Autowired自动注入
注入点:属性、构造方法、普通方法
遍历所有的注入点【方法—>注入点】
静态属性无法自动注入进去,源码会爆出非法异常
1.ClassPathXmlApplicationContext
2.AnniocationConfigApplication.getBean
启动spring的过程为:
bean生命周期
1.启动spring ClassPathXmlApplicationContext AnniocationConfigApplication.getBean 2.扫描 从配置类Appconfig中得到路径 得到Componment注解,得到类 3.懒加载单例bean 扫描出来的信息,进行保存BeanDefination到 CounrrentHashMap1.3 Spring循环依赖中进行过滤 根据BeanDefination得到Bean是否是单例Bean,如果原型,每次创建Bean,如果单例Bean,去单例池中拿 BeanDefination【类型,Scope[prototype原型Bean,Singleton单例Bean],lazy懒加载机制】 4.创建Bean---> doCreateBean(beanName,BeanDefination) 先看看单例中有没有吗,没有则创建然后放入到单例池中 创建单例池的Bean---> CounrrentHashMap(bean,beanDefination) 5.一、实例化 beanDefination.getBeanClass() 反射得到Bean,返回对象。 Bean容器利用java 反射机制实例化Bean 6.二、属性赋值 beanClass.getDeclaredFields()遍历属性,看看有什么属性 field.set()赋值 若Bean实现了BeanNameAware接口,调用setBeanName()方法 若Bean实现了BeanClassLoderAware接口,调用setBeanClassLoder()方法 若Bean实现了BeanFactoryAware接口,则执行setBeanFactory方法 如果Bean实现了ApplicationContextAware接口,则执行setApplicationContext方法; // 相当于切面,初始化之前,初始化之后 做什么事情 如果加载了BeanPostProcessor相关实现类,则执行postProcessBeforeInitialization方法; 7.如果Bean实现了InitializingBean接口,则执行afterPropertiesSet方法; 如果Bean定义初始化方法(PostConstruct注解或者配置的init-method),则执行定义的初始化方法; 如果加载了BeanPostProcessor相关实现类,则执行postProcessAfterInitialization方法; 8.当要销毁这个Bean时,如果Bean实现了DisposableBean接口,则执行destroy方法。
文章核心:spring循环依赖细节总结
循环依赖细节总结
一级缓存:缓存最终的单例池对象: private final Map1.4 二级缓存就已经解决了循环依赖了,为神魔需要三级缓存?singletonObjects = new ConcurrentHashMap<>(256); 二级缓存:缓存初始化的对象: private final Map earlySingletonObjects = new ConcurrentHashMap<>(16); 三级缓存:缓存对象的ObjectFactory: private final Map > singletonFactories = new HashMap<>(16);
一个缓存其实就是两个Map,A B 就能解决问题了
正常的场景一般没有问题,有什么特殊场景会有问题?
在上面第5步里面,Bean的后置处理器BeanPostProcessor,可能会进行AOP 1.如果配置了切面AOP才会进行AOP,AOP底层是采用动态代理实现的【JDK CGLIB】 2.AOP会生成一个代理对象,一个原始对象,一个代理对象,肯定会把代理对象放入到单例池中 3.在原始对象赋值的时候,执行完毕后,代理对象放入后会发生冲突,而B属性是原始对象 问题解决: 1.一个原始对象,一个代理对象,AOP提前进行,在原始对象之后就进行生成代理对象,全部都是代理对象了 原始对象--->AOP--->代理对象--->放入缓存Map 没有问题了1.5 Bean对象和创建的对象有什么区别?
// UserService 里面有一个User属性 UserService userService = context.getBean("userService",UserService.class); // 单例决定 UserService userService2 = new UserService();
1.引用地址不同
2.Bean里面的User是有值的【自动填充属性】,而new出来的是没有的
BeanDefination【ByType、ByName类型,Scope[prototype原型Bean,Singleton单例Bean], lazy懒加载机制】
3.懒加载单例bean 扫描出来的信息,进行保存BeanDefination到 CounrrentHashMap1.7 什么是 BeanPostProcessor 后置处理器?中进行过滤 根据BeanDefination得到Bean是否是单例Bean,如果原型,每次创建Bean,如果单例Bean,去单例池中拿 4.创建Bean---> doCreateBean(beanName,BeanDefination) 先看看单例中有没有吗,没有则创建然后放入到单例池中 创建单例池的Bean---> CounrrentHashMap(bean,beanDefination)
等待组件初始化完成,后置处理器才会工作
1.如BeanFactoryPostProcessor *** 作BeanFactory
2.包扫描,扫到@Component后,就会生成BeanDefination定义
如 BeanFactoryPostProcessor BeanFactory级别的处理,是针对整个Bean的⼯⼚进⾏处理,典型应⽤:PropertyPlaceholderConfigurer(属性替换符),此接⼝只提供了⼀个⽅法 1.其中有个⽅法名为getBeanDefinition的⽅法,我们可以根据此⽅法,找到我们定义bean 的BeanDefinition对象。然后我们可以对定义的属性进⾏修改,以下是BeanDefinition中的⽅法 2.⽅法名字类似我们bean标签的属性,setBeanClassName对应bean标签中的class属性,所以当我们拿到BeanDefinition对象时,我们可以⼿动修改bean标签中所定义的属性值。1.8 BeanFactory与ApplicationContext的区别?
ApplicationContext是BeanFactory的一种实现
通常情况,BeanFactory 的实现是使用懒加载的方式,这意味着 beans 只有在我们通过 getBean() 方法直接调用它们时才进行实例化实现 BeanFactory 最常用的 API 是 XMLBeanFactory
public class HelloWorldApp { public static void main(String[] args) { XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("beans.xml")); HelloWorld obj = (HelloWorld) factory.getBean("helloWorld"); obj.getMessage(); } }
ApplicationContext 接口
ApplicationContext 是 Spring 应用程序中的中央接口,用于向应用程序提供配置信息它继承了 BeanFactory 接口,所以 ApplicationContext 包含 BeanFactory 的所有功能以及更多功能!它的主要功能是支持大型的业务应用的创建特性:
Bean instantiation/wiring
Bean 的实例化/串联
自动的 BeanPostProcessor 注册
自动的 BeanFactoryPostProcessor 注册
方便的 MessageSource 访问(i18n)
ApplicationEvent 的发布与 BeanFactory 懒加载的方式不同,它是预加载,所以,每一个 bean 都在 ApplicationContext 启动之后实例化
public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); HelloWorld obj = (HelloWorld) context.getBean("helloWorld"); obj.getMessage(); }1.9 BeanFactory 与 FactoryBean的区别??
BeanFactory
这个其实是所有Spring Bean的容器根接口,给Spring 的容器定义一套规范,给IOC容器提供了一套完整的规范,比如我们常用到的getBean方法等
getBean(String name): Spring容器中获取对应Bean对象的方法,如存在,则返回该对象 containsBean(String name):Spring容器中是否存在该对象 isSingleton(String name):通过beanName是否为单例对象 isPrototype(String name):判断bean对象是否为多例对象 isTypeMatch(String name, ResolvableType typeToMatch):判断name值获取出来的bean与typeToMath是否匹配 getType(String name):获取Bean的Class类型 getAliases(String name):获取name所对应的所有的别名
使用ClassPathXmlApplicationContext读取对应的xml文件实例对应上下文对象
FactoryBean
该类是SpringIOC容器是创建Bean的一种形式,这种方式创建Bean会有加成方式,融合了简单的工厂设计模式于装饰器模式
T getObject():返回实例 Class> getObjectType();:返回该装饰对象的Bean的类型 default boolean isSingleton():Bean是否为单例
区别:
BeanFactory:负责生产和管理Bean的一个工厂接口,提供一个Spring Ioc容器规范, FactoryBean: 一种Bean创建的一种方式,对Bean的一种扩展。对于复杂的Bean对象初始化创建使用其可封装对象的创建细节。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)