从之前的ioc部分的源码分析等,我们对spring-ioc部分的相关已经有了一部分认识和了解,但是还是有很多人对里面一些部分的理解还是很模糊,好比既然有了beanFactory那factoryBean是干什么的,在ioc中有很多相关的aware这种后缀的类的命名,感觉应该有声明上的相似,但是却可能在之前的文章都一笔带过了...
鉴于诸如此类的,我想通过demo的方式,从表现形式上来区分所谓的beanFactory和FactoryBean,以及aware这类的意义
BeanFactory与FactoryBean
对于FactoryBean而言,想要体现factoryBean的强大的话,需结合AOP才能体现出来其强大,这里我们先初步分析,留待之后与AOP结合分析,为什么要与AOP结合分析,我们先看看官方描述
出自FactoryBean官方注释说明: A bean that implements this interface cannot be used as a normal bean. A FactoryBean is defined in a bean style, but the object exposed for bean references ({@link #getObject()}) is always the object that it creates. This interface is heavily used within the framework itself, for example for the AOP {@link org.springframework.aop.framework.ProxyFactoryBean} or the {@link org.springframework.jndi.JndiObjectFactoryBean}. It can be used for custom components as well; however, this is only common for infrastructure code. 虽然FactoryBean定义为一个bean的形式,但是会通过getObject方法将一些对象暴露出来,我们可以通过ProxyFactoryBean的getObject中先了解下可知任何实现了beanFactory的bean都可通过getObject获取这个类型的bean 官方在AOP的ProxyFactoryBean或JndiObjectFactoryBean中有这两个类可作为示例,接口是在框架内大量使用,也能被使用在自定义的组建,然后这个仅在基础结构代码中常见
上一篇咱们简单的提及了factoryBean, 我们借助beanFactory通过"&"+beanName的方法查找class,现在我们就看下spring对这块的官方说明
即在beanFactory中有这一个说明,就是其通过&这个符号来获取factoryBean,到此factoryBean我们就了解到,其FactoryBean的getObject()返回的对象,而不是FactoryBean本身, 如果要获取FactoryBean对象,可以在id前面加一个&符号来获取
废话不多说直接上实例:
首先我们既然要看factorybean,那我们就实现一个,既然官方为我们提供了ProxyFactoryBean和JndiObjectFactoryBean中两个类作为示例,那我们就从示例中类比写出一个简单的factoryBean来印证
-
实现factorybean接口
public class ProxyMyFactoryBean implements FactoryBean { public Object getObject() throws Exception { return null; } public Class<?> getObjectType() { return null; } public boolean isSingleton() { return false; } }
-
factoryBean中只有三个方法,我们一边结合官方注释和官方示例的ProxyFactoryBean来"丰满"各个方法
-
getObject方法
在这里插入图片描述官方的描述是这样的"返回一个在factory中被管理的类的实例"
-
isSingleton()方法
在这里插入图片描述即在factory中被管理的类是否是单例的
在ProxyFactoryBean中其实现的getObject()的方法用了以上两个方法
在这里插入图片描述我们不关心其中间的实现,我们就关注其返回结果,可发现,如果是单例的话,就通过创建单例的方式创建一个实例返回,否则的话,就直接创建一个对象返回
-
getObjectType方法
在这里插入图片描述可了解其是返回factoryBean创建的实例的类型,可能有些人跟我一样理解不了要这玩意儿干啥,我们再看看其具体描述"这个方法允许在不实例化对象的情况下检查特定类型的bean,例如在autowiring时",感觉有点用还是不太清楚,看看示例辅助下
在这里插入图片描述从这里我们也关注其返回的结果,
- 单例实例时,就返回该实例的class对象,否则的话获取代理接口,
- 如果是一个的多就返回该代理接口的class对象
- 如果是多个的话就创建一个组合接口的class对象
- 如果targetName不为null且beanFactory不为null就从beanFactory中找到tagetName的class类型返回
- 如果均不符合,那就返回targetSource的class
简单理解就是返回我们getObject创建实例的关联类的class
-
-
"丰满"我们的factoryBean
-
准备工作,由于其是返回示例所以我们需要创建类来辅助我们
public class TargetA { public void print() { System.out.println("-----print--AAA----succeed---"); } } public class TargetB { public void print() { System.out.println("-----print--BBB----succeed---"); } }
-
"丰满”工作
public class ProxyMyFactoryBean implements FactoryBean { private String targetName; public void setTargetName(String targetName) { this.targetName = targetName; } public Object getObject() throws Exception { if("aaa".equals(targetName)) { return new TargetA(); } return new TargetB(); } public Class<?> getObjectType() { if("aaa".equals(targetName)) { return TargetA.class; } return TargetB.class; } public boolean isSingleton() { return false; } }
-
创建bean的xml配置factorybean信息
<bean id="proxyMyFactoryBean" class="org.tutor.spring.ioc.bean.ProxyMyFactoryBean"> <property name="targetName" value="aaa"/> </bean>
-
运行结果
在这里插入图片描述从其运行结果我们都能获取到targetA的实例用以操控
-
-
总结
beanFactory就不在此处详细介绍,不过我们做一下从上面运行的方式,我们都能看到无论beanFactory还是FactoryBean我们都能获取我们想要的实例对象
beanFactory相当于bean的容器,可以理解成工厂,内可以帮我们创建bean,对bean进行管理
-
factoryBean虽然也可以创建bean,其更多的是对class上进行代理处理,从我们的测试方法,我们很容易就可以想到,明显代理的痕迹
这里我引用一张图加以理解
在这里插入图片描述就是我们通过设置目标的class属性从factoryBean中获取目标class的代理对象
可能有人会疑问为什么会有这样的设计,其实spring在aop中已经回答我们,不过我们也可以从代理模式的优点能理解其意义也是可以
- 在符合开闭原则的情况下对目标对象进行功能扩展
那么我们就可以大胆的猜想,其就是为了让我们在持有目标对象时,丰富对象功能,也可以不在关注具象实现,有需求方关注(具体我们在AOP处,对ProxyFactoryBean的应用处可了解)
BeanNameAware与BeanFactoryAware
BeanNameAware是对于需要获取在beanFactory的beanName的时候就实现
BeanFactoryAware是由对应的BeanFactory实现的,即可获取该bean所在的beanFactory名称,可以获取配置他们的BeanFactory的引用
总结
由于BeanNameAware和BeanFactoryAware均都是spring内实现,故其实对我们应用及其有限,但它们对spring而言,却不一样,我们可以从spring代码书写来理解
-
BeanNameAware
在这里插入图片描述类似这样,本身springLifeBean没有什么意义,只是我们做的一个标记,便于理解
-
BeanFactoryAware
这个方法可能是在根据某个配置文件创建了一个新工厂之后,Spring才调用这个方法,并把BeanFactory注入到Bean中。
让bean获取配置自己的工厂之后,当然可以在Bean中使用这个工厂的getBean()方法,但是,实际上非常不推荐这样做,因为结果是进一步加大Bean与Spring的耦合,而且,能通过DI注入进来的尽量通过DI来注入。
当然,除了查找bean,BeanFactory可以提供大量其他的功能,例如销毁singleton模式的Bean。
factory.preInstantiateSingletons();方法。preInstantiateSingletons()方法立即实例化所有的Bean实例,有必要对这个方法和Spring加载bean的机制做个简单说明。
方法本身的目的是让Spring立即处理工厂中所有Bean的定义,并且将这些Bean全部实例化。因为Spring默认实例化Bean的情况下,采用的是lazy机制,换言之,如果不通过getBean()方法(BeanFactory或者ApplicationContext的方法)获取Bean的话,那么为了节省内存将不实例话Bean,只有在Bean被调用的时候才实例化它们引用自网上对BeanFactoryAware的描述
Springbean的初始化顺序
对于IOC我们也分析有一段时间了,既然IOC是对bean的操作,那么我们还没有正面关注过,接下来,通过bean的初始化过程,继续巩固一路走来的IOC分析
在我们分析SpringFactory的refresh时候,其依次顺序是aware 然后InitializingBean,最后进入的是postProcessor,那我们通过实现这些接口看看其的顺序是否跟我们的refresh分析是否相左
-
准备工作
创建一个类,实现'BeanFactoryAware,BeanNameAware,BeanFactoryPostProcessor,BeanPostProcessor,InitializingBean'这些接口
public class TestLifeCycleBean implements BeanFactoryAware,BeanNameAware,BeanFactoryPostProcessor,BeanPostProcessor,InitializingBean { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public TestLifeCycleBean() { System.out.println("into... 构造函数"); } /** * init-method */ public void initMethod(){ System.out.println("into... init-method"); } public void say(){ System.out.println("into... say hello I am "+name); } public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("into... setBeanFactory and beanFactory is "+beanFactory); } public void setBeanName(String s) { System.out.println("into... setBeanName and name is "+s); } public void afterPropertiesSet() throws Exception { System.out.println("into... InitializingBean接口的afterPropertiesSet and name is "+ name); } public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { System.out.println("into... BeanFactoryPostProcessor接口的postProcessBeanFactory and this beanFactory is "+configurableListableBeanFactory); } public Object postProcessBeforeInitialization(Object o, String s) throws BeansException { System.out.println("into... BeanPostProcessor接口的postProcessBeforeInitialization: "+o.getClass()); return o; } public Object postProcessAfterInitialization(Object o, String s) throws BeansException { System.out.println("into... BeanPostProcessor接口的postProcessAfterInitialization: "+o.getClass()); return o; } }
在这里可能我们打印的结果可能是这样的
在这里插入图片描述很明显BeanPostProcessor的相关方法并没有产生作用,这是我们之前的大战BeanPostProcessor有说明,我们只用实例化一个bean即可
在这里插入图片描述总结其springbean的初始化顺序
- 1.先执行构造函数
- 2.之行BeanNameAware方法
- 3.执行BeanFactoryAware方法
- 4.之行InitializingBean方法
- 5.执行指定的init-method方法
- 6.执行BeanFactoryPostProcessor方法
- 7.最后才有BeanPostProcessor方法
回顾之前的refresh
有没有豁然开朗的感觉?!就先整理这些吧,持续整理更新....