说在前面:
可能会疑惑之前不是学了两种方式吗:beanFactory和applicationContext。最根本来讲,就是通过工厂模式创建。
是的,是工厂模式创建,但又分了两种方式:构造+工厂
-
构造方法
其中又分为了无参构造和有参构造。
在默认情况下,工厂就是通过无参构造来创建bean的,如果我们提供的是有参构造的话,就需要在配置中添加参数
public ServiceImpl(String chineseName){ System.out.println("有参构造方法执行"); }
//xml配置实现 <bean id="Service" class="com.demo.impl.ServiceImpl"> <constructor-arg name="chineseName" value="lihua"/> </bean>
-
工厂
这个工厂同前面说的工厂不一样,这里的工厂是自己来提供的,工厂里套工厂。
其中也分为三种方式。
-
静态工厂
设置一个静态方法
public class ServiceImpl implements Service{ public static UserDaoImpl userDaoimpl(){ return new UserDaoImpl(); } }
<bean id="Service" class="com.demo.impl.ServiceImpl" factory-method="userDaoimpl"> </bean> //输出结果 com.demo.impl.UserDaoImpl@5af97850
<bean id="Service" class="com.demo.impl.ServiceImpl" ></bean> //输出结果 com.demo.impl.ServiceImpl@1b083826
在这里我设置了两种情况,区别就在于是否指定了factory-method方法。
这样设置的好处是什么呢?
好处之一:可以在我们创建实例之前完成一些其他操作。拿返回的new UserDaoImpl()举例,在我们返回之前啊,我们可以先把这个实例提出来去完成其他方法,最后才将它给返回。
好处之二:在这些bean中,基本都是我们自己定义的,比如ServiceImpl,UserDaoImpl等等,在开发中,我们还会延用java自有的一些jar包,人家写的bean可能就不是通过构造方法写的,这种时候就可能需要用到工厂来延用。
-
实例工厂
这个与静态工厂的区别就在于它的方法不是静态的。所以我们就必须先让容器给我们产生一个对象,然后我们拿着这个对象去调用相应的方法,最后返回我们想要的实例bean。然后在底层中我们也可以了解到:如果是实例工厂,它可以将我们自定义的bean(如下文的ServiceImpl)放在单例池中储存起来,而静态工厂不行。
public class ServiceImpl implements Service{ public UserDaoImpl userDaoimpl(){ return new UserDaoImpl(); } }
//先创造出一个对象 <bean id="Service" class="com.demo.impl.ServiceImpl" ></bean> //然后让对象去实现某个方法 <bean id="UserDao" factory-bean="Service" factory-method="userDaoimpl"></bean>
-
注意啊,这里我们工厂中的bean是没有带任何参数的,当我们需要参数时,也是可以直接通过xml中的constructor-arg 来进行配置。这个constructor-arg 它并不只是构造函数设参数,只要我们的bean的方法中需要用到参数都可以用它来配置。
-
FactoryBean的规范延迟
什么是FactoryBean,我们先看下源码来了解下
public interface FactoryBean<T> { String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType"; @Nullable T getObject() throws Exception;//主要靠的就是这个方法,用它来给我们返回规范的bean实例 @Nullable Class<?> getObjectType();//返回对象类型 default boolean isSingleton() {//是否单例 return true; } }
可以看到,FactoryBean实际上就是一个接口,内部提供了几个方法给我们,"当配置某个bean实现了FactoryBean接口时,该bean返回的对象不是FactoryBean本身,而是FactoryBean#getObject()方法返回的对象,这就提供了一种扩展的可能,我们可以在这个方法里定制创建逻辑。"这样看来,又好像和静态、实例工厂也没什么区别嘛。其实它的区别也就在于它自身的规范性,我们把bean扔给他,就不再需要额外给它指明bean方法了。
public class ServiceImpl implements Service, FactoryBean<UserDaoImpl> { @Override public UserDaoImpl getObject() throws Exception { return new UserDaoImpl(); } }
在xml中
<bean id="Service" class="com.demo.impl.ServiceImpl" ></bean>
即可实现bean的实例创建。