前言
理解FactoryBean是非常非常有必要的,因为在Spring中FactoryBean最为典型的一个应用就是用来创建AOP的代理对象,不仅如此,而且对理解Mybatis核心源码也非常有帮助!如果甘愿crud,做个快乐的码农,那我就哦豁豁豁豁豁豁豁豁豁豁豁豁豁豁......
@
- 1、BeanFactory
- 1.1 BeanFactory 源码
- 1.2、BeanFactory 使用场景
- 2、FactoryBean
- 2.1、为什么会有FactoryBean?
- 2.2 、FactoryBean 源码
- 2.3 、FactoryBean代码示例
- 2.4 FactoryBean使用场景
BeanFactory和FactoryBean同样都是spring的接口,名字看起来很相似,但是我觉得要混淆还是很困难的!尽管Spring揭秘一书的作者都喜欢写上这一句。
请不要混淆BeanFactory 和 FactoryBean。
1、BeanFactory
BeanFactory,以Factory结尾,表示它是一个工厂(接口), 它负责生产和管理bean的一个工厂。在Spring中,BeanFactory是工厂的顶层接口,也是IOC容器的核心接口,因此BeanFactory中定义了管理Bean的通用方法,如 getBean 和 containsBean 等,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。BeanFactory只是个接口,并不是IOC容器的具体实现,所以Spring容器给出了很多种实现,如 DefaultListableBeanFactory、、ApplicationContext等,其中 1、从Ioc容器中获取Bean(byName or byType) 首先FactoryBean是一个Bean,但又不仅仅是一个Bean,这样听起来矛盾,但为啥又这样说呢?其实在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的。但对FactoryBean而言,这个FactoryBean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似 一般情况下,Spring通过反射机制利用 1、 2、 方法介绍: 3、 FactoryBean表现的是一个工厂的职责。 即一个Bean A如果实现了FactoryBean接口,那么A就变成了一个工厂,根据A的名称获取到的实际上是工厂调用getObject()返回的对象,而不是A本身,如果要获取工厂A自身的实例,那么需要在名称前面加上'&'符号。 通俗点表达就是 getObject(' name ')返回工厂中的实例 通常情况下,bean 无须自己实现工厂模式,Spring 容器担任了工厂的 角色;但少数情况下,容器中的 bean 本身就是工厂,作用是产生其他 bean 实例。由工厂 bean 产生的其他 bean 实例,不再由 Spring 容器产生,因此与普通 bean 的配置不同,不再需要提供 class 元素。 1、创建一个Appconfig类,扫描com.yichun下的所有子包 2、创建一个StudentBean类并实现FactoryBean,并重写其两个方法 3、再创建一个TeacherBean类 4、测试StudentBean类型 5、测试一下teacherBean类型 运行成功 使用场景一: 所以,FactoryBean为我们实例化Bean提供了一个更为灵活的方式,我们可以通过FactoryBean创建出更为复杂的Bean实例。 当然在spring中,Spring容器内部许多地方了使用FactoryBean。下面是一些比较常见的FactoryBean实现: JndiobjectFactoryBean 使用场景二: 另外提一下,阿里开源的分布式服务框架 Dubbo中的Consumer 也使用到了FactoryBean, 使用场景三: 最后本文难免会有不正之处,欢迎指正评判!欢迎指正评判!欢迎指正评判!!! 参考: 原文转载:http://www.shaoqun.com/a/488027.html google correlate:https://www.ikjzd.com/w/1887 海豚村:https://www.ikjzd.com/w/1779 中转贸易:https://www.ikjzd.com/w/14271.1 BeanFactory 源码
public interface BeanFactory { //对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象, //如果需要得到工厂本身,需要转义 String FACTORY_BEAN_PREFIX = "&"; //根据bean的名字,获取在IOC容器中得到bean实例 Object getBean(String name) throws BeansException; //根据bean的名字和Class类型来得到bean实例,增加了类型安全验证机制。 <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException; Object getBean(String name, Object... args) throws BeansException; <T> T getBean(Class<T> requiredType) throws BeansException; <T> T getBean(Class<T> requiredType, Object... args) throws BeansException; //提供对bean的检索,看看是否在IOC容器有这个名字的bean boolean containsBean(String name); //根据bean名字得到bean实例,并同时判断这个bean是不是单例 boolean isSingleton(String name) throws NoSuchBeanDefinitionException; boolean isPrototype(String name) throws NoSuchBeanDefinitionException; boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException; boolean isTypeMatch(String name, @Nullable Class<?> typeToMatch) throws NoSuchBeanDefinitionException; //得到bean实例的Class类型 @Nullable Class<?> getType(String name) throws NoSuchBeanDefinitionException; //得到bean的别名,如果根据别名检索,那么其原名也会被检索出来 String[] getAliases(String name);}1.2、BeanFactory 使用场景
2、检索Ioc容器中是否包含指定的Bean
3、判断Bean是否为单例2、FactoryBean
2.1、为什么会有FactoryBean?
在某些情况下,实例化Bean过程比较复杂,如果按照传统的方式,则需要在org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。FactoryBean接口对于Spring框架来说占用重要的地位,Spring自身就提供了70多个FactoryBean的实现。它们隐藏了实例化一些复杂Bean的细节,给上层应用带来了便利。
由于第三方库不能直接注册到spring容器,于是可以实现org.springframework.bean.factory.FactoryBean接口,然后给出自己对象的实例化代码即可。2.2 、FactoryBean 源码
public interface FactoryBean<T> { //从工厂中获取bean【这个方法是FactoryBean的核心】 @Nullable T getObject() throws Exception; //获取Bean工厂创建的对象的类型【注意这个方法主要作用是:该方法返回的类型是在ioc容器中getbean所匹配的类型】 @Nullable Class<?> getObjectType(); //Bean工厂创建的对象是否是单例模式 default boolean isSingleton() { return true; }}
1、
getobject ()方法会返回该FactoryBean "生产" 的对象实例,我们需要实现该方法以给出自己的对象实例化逻辑;
2、
getobjectTYype ()方法仅返回getobject ()方法所返回的对象的类型,如果预先无法确定,则返回null; 特别注意这个方法主要作用是:该方法返回的类型是在ioc容器中getbean所匹配的类型,也就是说ioc中有很多类型的bean,要找到这个bean就是通过getobjectTYype ()方法的返回值类型!好吧,我举个例子public class XXX implements FactoryBean { @Override public Object getObject() throws Exception { return new YYY; } @Override public Class<?> getObjectType() { //注意这个方法主要作用是:该方法返回的类型是在ioc容器中getbean所匹配的类型 return AAA.class; }}那么要想在ioc中找到XXX这个类的bean(实际上是YYY) ,在getbean的时候写法如下public class Demo1 { public static void main(String[] args) { AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Appconfig.class); annotationConfigApplicationContext.getBean( AAA.class ); // 【注意这里是AAA.class】 }}
isSingleton ()方法返回结果用于表明,工厂方法(getobject ())所"生产"的对象是否要以singleton形式存在于容器中。如果以singleton形式存在,则返回true,否则返回false;
getObject(' &name ')返回工厂本身的实例2.3 、FactoryBean代码示例
@Configuration@ComponentScan("com.yichun")public class Appconfig {}@Component("studentBean")public class StudentBean implements FactoryBean { @Override public Object getObject() throws Exception { return new TeacherBean(); } @Override public Class<?> getObjectType() { //注意这个方法主要作用是:该方法返回的类型是在ioc容器中getbean所匹配的类型 return StudentBean.class; } //一个学生学习方法 public void study(){ System.out.println("学生学习。。。"); }}public class TeacherBean { public void teacher(){ System.out.println("老师教书。。。。"); }}public class Demo1 { public static void main(String[] args) { AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Appconfig.class); StudentBean studentBean = (StudentBean)annotationConfigApplicationContext.getBean("studentBean"); studentBean.study(); }}
加上"&"符号public class Demo1 { public static void main(String[] args) { AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Appconfig.class); //加上了"&"符号 StudentBean studentBean = (StudentBean)annotationConfigApplicationContext.getBean("&studentBean"); studentBean.study(); }}
运行成功public class Demo1 { public static void main(String[] args) { AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Appconfig.class); TeacherBean teacherBean = (TeacherBean) annotationConfigApplicationContext.getBean("studentBean"); teacherBean.teacher(); }}
2.4 FactoryBean使用场景
FactoryBean在Spring中最为典型的一个应用就是用来创建AOP的代理对象。
我们知道AOP实际上是Spring在运行时创建了一个代理对象,也就是说这个对象,是我们在运行时创建的,而不是一开始就定义好的,这很符合工厂方法模式。更形象地说,AOP代理对象通过Java的反射机制,在运行时创建了一个代理对象,在代理对象的目标方法中根据业务要求织入了相应的方法。这个对象在Spring中就是——ProxyFactoryBean。
LocalSessionFactoryBean
SqlMapClientFactoryBean
ProxyFactoryBean
TransactionProxyFactoryBean
Mybatis中的SqlSessionFactoryBean<bean id="tradeSqlSessionFactory" > <property name="dataSource" ref="trade" /> <property name="mapperLocations" value="classpath*:mapper/trade/*Mapper.package org.mybatis.spring;public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {private static final Log LOGGER = LogFactory.getLog(SqlSessionFactoryBean.class); ......}<beans <dubbo:reference 对应的Bean是com.alibaba.dubbo.config.spring.ReferenceBean 类。
Hibernate中的SessionFactoryBean。这里就不再概述。
《Spring揭秘》王福强
https://zhuanlan.zhihu.com/p/87382038
https://www.cnblogs.com/aspirant/p/9082858.html
前言理解FactoryBean是非常非常有必要的,因为在Spring中FactoryBean最为典型的一个应用就是用来创建AOP的代理对象,不仅如此,而且对理解Mybatis核心源码也非常有帮助!如果甘愿crud,做个快乐的码农,那我就哦豁豁豁豁豁豁豁豁豁豁豁豁豁豁......@目录1、BeanFactory1.1BeanFactory源码1.2、BeanFactory使用场景2、FactoryB
barclays:https://www.ikjzd.com/w/2775
1号团:https://www.ikjzd.com/w/2263
甘肃敦煌自由行最新攻略:http://tour.shaoqun.com/a/67500.html
兴业鹿峰山暑假优惠活动?鹿峰山暑期优惠?:http://tour.shaoqun.com/a/58226.html
漫步三亚酒吧街乐美风暖熏得游人醉 :http://tour.shaoqun.com/a/52240.html
No comments:
Post a Comment