2、检索Ioc容器中是否包含指定的Bean 3、判断Bean是否为单例
2、FactoryBean
首先FactoryBean是一个Bean,但又不仅仅是一个Bean,这样听起来矛盾,但为啥又这样说呢?其实在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的。但对FactoryBean而言,这个FactoryBean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似
2.1、为什么会有FactoryBean?
一般情况下,Spring通过反射机制利用的class属性指定实现类实例化Bean。至于为什么会有FactoryBean?原因有两个:
1、 在某些情况下,实例化Bean过程比较复杂,如果按照传统的方式,则需要在中提供大量的配置信息。配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。FactoryBean接口对于Spring框架来说占用重要的地位,Spring自身就提供了70多个FactoryBean的实现。它们隐藏了实例化一些复杂Bean的细节,给上层应用带来了便利。
2、 由于第三方库不能直接注册到spring容器,于是可以实现org.springframework.bean.factory.FactoryBean接口,然后给出自己对象的实例化代码即可。
2.2 、FactoryBean 源码
public interface FactoryBean {
//从工厂中获取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】
}
}
3、 isSingleton ()方法返回结果用于表明,工厂方法(getobject ())所“生产”的对象是否要以singleton形式存在于容器中。如果以singleton形式存在,则返回true,否则返回false;
FactoryBean表现的是一个工厂的职责。 即一个Bean A如果实现了FactoryBean接口,那么A就变成了一个工厂,根据A的名称获取到的实际上是工厂调用getObject()返回的对象,而不是A本身,如果要获取工厂A自身的实例,那么需要在名称前面加上’&'符号。 通俗点表达就是
getObject(’ name ‘)返回工厂中的实例 getObject(’ &name ')返回工厂本身的实例
通常情况下,bean 无须自己实现工厂模式,Spring 容器担任了工厂的 角色;但少数情况下,容器中的 bean 本身就是工厂,作用是产生其他 bean 实例。由工厂 bean 产生的其他 bean 实例,不再由 Spring 容器产生,因此与普通 bean 的配置不同,不再需要提供 class 元素。
2.3 、FactoryBean代码示例
1、创建一个Appconfig类,扫描com.yichun下的所有子包
@Configuration
@ComponentScan(“com.yichun”)
public class Appconfig {
}
2、创建一个StudentBean类并实现FactoryBean,并重写其两个方法
@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(“学生学习。。。”);
}
}
3、再创建一个TeacherBean类
public class TeacherBean {
public void teacher(){
System.out.println(“老师教书。。。。”);
}
}
4、测试StudentBean类型
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();
}
}
运行成功
5、测试一下teacherBean类型
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。
所以,FactoryBean为我们实例化Bean提供了一个更为灵活的方式,我们可以通过FactoryBean创建出更为复杂的Bean实例。
当然在spring中,Spring容器内部许多地方了使用FactoryBean。下面是一些比较常见的FactoryBean实现:
JndiobjectFactoryBean
LocalSessionFactoryBean SqlMapClientFactoryBean ProxyFactoryBean TransactionProxyFactoryBean
使用场景二: Mybatis中的SqlSessionFactoryBean
总结
面试难免让人焦虑不安。经历过的人都懂的。但是如果你提前预测面试官要问你的问题并想出得体的回答方式,就会容易很多。
此外,都说“面试造火箭,工作拧螺丝”,那对于准备面试的朋友,你只需懂一个字:刷!
给我刷刷刷刷,使劲儿刷刷刷刷刷!今天既是来谈面试的,那就必须得来整点面试真题,这不花了我整28天,做了份“Java一线大厂高岗面试题解析合集:JAVA基础-中级-高级面试+SSM框架+分布式+性能调优+微服务+并发编程+网络+设计模式+数据结构与算法等”
且除了单纯的刷题,也得需准备一本【JAVA进阶核心知识手册】:JVM、JAVA集合、JAVA多线程并发、JAVA基础、Spring 原理、微服务、Netty与RPC、网络、日志、Zookeeper、Kafka、RabbitMQ、Hbase、MongoDB、Cassandra、设计模式、负载均衡、数据库、一致性算法、JAVA算法、数据结构、加密算法、分布式缓存、Hadoop、Spark、Storm、YARN、机器学习、云计算,用来查漏补缺最好不过。
、网络、日志、Zookeeper、Kafka、RabbitMQ、Hbase、MongoDB、Cassandra、设计模式、负载均衡、数据库、一致性算法、JAVA算法、数据结构、加密算法、分布式缓存、Hadoop、Spark、Storm、YARN、机器学习、云计算,用来查漏补缺最好不过。
[外链图片转存中…(img-Z4mkYB6c-1720120758013)]