Original text: cnblogs.com/aspirant/p/9082858.html

Introduction to the

BeanFacotry is the primitive Factory in Spring. XMLBeanFactory, for example, is a typical BeanFactory. The original BeanFactory didn’t support many of Spring’s plug-ins, such as AOP functionality, Web applications, and so on.

The ApplicationContext interface, derived from the BeanFactory interface. The ApplicationContext contains all the functionality of the BeanFactory and is generally recommended to take precedence over the BeanFactory.

The difference between BeanFactory and FactoryBean

BeanFactory is an interface that provides the most basic form of an OC container and a specification for the implementation of a specific IOC container.

Factorybeans are also interfaces that provide a more flexible way to implement beans in IOC containers. Factorybeans add a simple factory pattern and a decorator pattern to the implementation of beans in IOC containers. The decorator pattern (decorator pattern) can be configured flexibly in the getObject() method. There are many FactoryBean implementation classes in the Spring source code.

Difference: BeanFactory is an IOC container or object Factory, and FactoryBean is a Bean. In Spring, all beans are managed by the BeanFactory(i.e. IOC container).

For a FactoryBean, however, this Bean is not a simple Bean, but a FactoryBean that produces or decorates the generation of objects. Its implementation is similar to that of the factory and decorator patterns in the design pattern

1, the BeanFactory

BeanFactory, which ends with Factory, indicates that it is a Factory class (interface) that is responsible for producing and managing a Factory for beans. In Spring, the BeanFactory is the core interface of the IOC container. Its responsibilities include instantiating, locating, configuring, and establishing dependencies between objects in an application.

The BeanFactory is just an interface, not the implementation of the IOC container, but the Spring container is given a lot of kinds of implementation, such as DefaultListableBeanFactory, XmlBeanFactory, ApplicationContext, etc., A common one is XmlBeanFactory, which describes in XML the objects that make up the application and the dependencies between them. The XmlBeanFactory class will hold this XML configuration metadata and use it to build a fully configurable system or application.

It’s an implementation with some function attached. It for other specific IOC container provides the most basic norms, for example, DefaultListableBeanFactory XmlBeanFactory, ApplicationContext of container are realized the BeanFactory, On top of that, other functions are added.

The BeanFactory and ApplicationContext are two IOC containers of the Spring framework. ApplicationnContext is now commonly used, which not only contains the functions of the BeanFactory, but also provides more extensions.

BeanFacotry is the primitive Factory in Spring. XMLBeanFactory, for example, is a typical BeanFactory.

The original BeanFactory didn’t support many of Spring’s plug-ins, such as AOP functionality, Web applications, and so on. The ApplicationContext interface, derived from the BeanFactory interface,

The ApplicationContext contains all the functionality of the BeanFactory and is generally recommended to take precedence over the BeanFactory

The ApplicationContext package, which works in a more framework oriented manner and hierarchies and inherits contexts, also provides the following functionality:

  • MessageSource, providing internationalized message access

  • Access to resources such as urls and files

  • Event propagation

  • Load multiple (inheritable) contexts so that each one is focused on a specific layer, such as the web layer of the application;

Before using the Spring framework, we had to create a new object in the Service layer to use objects from the DAO layer in the Service layer. The problem: Layer to layer dependencies.

Service layer to use the DAO layer objects need to be configured into the XML configuration file, how the objects are created and how the relationships are combined is left up to the Spring framework.

Methods 1,

Resource resource = new FileSystemResource("beans.xml");
BeanFactory factory = new XmlBeanFactory(resource);
Copy the code

Methods 2,

ClassPathResource resource = new ClassPathResource("beans.xml");
BeanFactory factory = new XmlBeanFactory(resource);
Copy the code

Methods 3,

ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"applicationContext.xml"."applicationContext-part2.xml"});
BeanFactory factory = (BeanFactory) context;
Copy the code

That’s about it, then use the getBean(String beanName) method to get the instance of the bean; The methods provided by BeanFactory are extremely simple, providing only six methods for customers to call:

  • Boolean containsBean(String beanName) Checks whether the factory contains the bean definition with the given name, and returns true if so

  • Object getBean(String) returns the bean instance registered with the given name. Depending on the configuration of the bean, the Singleton pattern will return a shared instance if it is the singleton pattern, otherwise a newly created instance will be returned, and this method may throw an exception if the specified bean is not found

  • Object getBean(String, Class) returns the bean instance registered with the given name and converted to the given Class type

  • Class getType (String name) returns the given name of the bean Class, if could not find the specified bean instance, will eliminate NoSuchBeanDefinitionException abnormal

  • Boolean isSingleton(String) Determines whether the bean definition with the given name is a singleton

  • String[] getAliases(String name) returns all aliases for the given bean name

package org.springframework.beans.factory;  
import org.springframework.beans.BeansException;  
public interface BeanFactory {  
    String FACTORY_BEAN_PREFIX = "&"; Object getBean(String name) throws BeansException; <T> T getBean(String name, Class<T> requiredType) throws BeansException; <T> T getBean(Class<T> requiredType) throws BeansException; Object getBean(String name, Object... args) throws BeansException; boolean containsBean(String name); boolean isSingleton(String name) throws NoSuchBeanDefinitionException; boolean isPrototype(String name) throws NoSuchBeanDefinitionException; boolean isTypeMatch(String name, Class<? > targetType) throws NoSuchBeanDefinitionException; Class<? > getType(String name) throws NoSuchBeanDefinitionException; String[] getAliases(String name); }Copy the code

2, FactoryBean

In general, Spring uses reflection to specify the implementation class to instantiate beans using the class attribute of

. In some cases, the process of instantiating beans is complicated and requires a lot of configuration information to be provided in

in the traditional way. The flexibility of configuration is limited, and coding may yield a simple solution.

Spring provides a org. Springframework. Beans. Factory. FactoryBean factory class interface, users can customize by implementing the interface logic instantiation of the bean. The FactoryBean interface plays an important role in the Spring framework. Spring itself provides over 70 FactoryBean implementations. They hide the details of instantiating complex beans for the benefit of upper-layer applications. As of Spring3.0, factorybeans began to support generics, meaning that the interface declaration was changed to the form of FactoryBean

End with Bean to indicate that it is a Bean. It is a Bean that implements the FactoryBean

interface. According to the Bean’s ID, what we get from BeanFactory is actually the object returned by getObject() of FactoryBean, not the FactoryBean itself. If you want to get a FactoryBean object, you get it by prefacing the ID with an ampersand.

For example, a FactoryBean can be used to proxy an object, intercept all methods of the object, and output a LOG line before and after the call, mimicking the functions of ProxyFactoryBean.

/** * my factory bean<p> * @author Daniel. Zhao * */ public class MyFactoryBean implements FactoryBean<Object>, DisposableBean { private static final Logger logger = LoggerFactory.getLogger(MyFactoryBean.class); private String interfaceName; private Object target; private Object proxyObj; @Override public void destroy() throws Exception { logger.debug("destroy......");
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        proxyObj = Proxy.newProxyInstance(
                this.getClass().getClassLoader(), 
                new Class[] { Class.forName(interfaceName) }, 
                new InvocationHandler() {                    
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                logger.debug("invoke method......" + method.getName());
                logger.debug("invoke method before......" + System.currentTimeMillis());
                Object result = method.invoke(target, args);
                logger.debug("invoke method after......" + System.currentTimeMillis());
                returnresult; }}); logger.debug("afterPropertiesSet......");
    }

    @Override
    public Object getObject() throws Exception {
        logger.debug("getObject......");
        returnproxyObj; } @Override public Class<? >getObjectType() {
        return proxyObj == null ? Object.class : proxyObj.getClass();
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    public String getInterfaceName() {
        return interfaceName;
    }

    public void setInterfaceName(String interfaceName) {
        this.interfaceName = interfaceName;
    }

    public Object getTarget() {
        return target;
    }

    public void setTarget(Object target) {
        this.target = target;
    }

    public Object getProxyObj() {
        return proxyObj;
    }

    public void setProxyObj(Object proxyObj) { this.proxyObj = proxyObj; }}Copy the code

The configuration of the XML-bean is as follows

<bean id="fbHelloWorldService" class="com.ebao.xxx.MyFactoryBean">
   <property name="interfaceName" value="com.ebao.xxx.HelloWorldService" />
   <property name="target" ref="helloWorldService" />
</bean>
Copy the code

Junit Test class

@RunWith(JUnit4ClassRunner.class) @ContextConfiguration(classes = { MyFactoryBeanConfig.class }) public class MyFactoryBeanTest { @Autowired private ApplicationContext context; /** * The FactoryBean test validates the principle of proxying a servcie before and after calling its methods. Get a custom FactoryBean from ApplicationContext * Context.getBean (String beanName) --> The final Object is factoryBean.getobejct (), which uses proxy.newinstance to generate a service Proxy class */ @test public voidtestFactoryBean() {
        HelloWorldService helloWorldService = (HelloWorldService) context.getBean("fbHelloWorldService"); helloWorldService.getBeanName(); helloWorldService.sayHello(); }}Copy the code

FactoryBean is an interface. When a Bean in an IOC container implements a FactoryBean, the Bean object obtained by getBean(String BeanName) is not the implementation class object of a FactoryBean. It is the object returned by the getObject() method in the implementation class. To get the implementation class of a FactoryBean, getBean(&BeanName) is preceded by &.

Java code

package org.springframework.beans.factory; public interface FactoryBean<T> { T getObject() throws Exception; Class<? > getObjectType(); boolean isSingleton(); }Copy the code

The following three methods are also defined in this interface:

  • TgetObject() : Returns the Bean instance created by FactoryBean. If isSingleton() returns true, the instance will be placed in the Spring container’s singleton cache pool;

  • BooleanisSingleton () : Returns whether the scope of the Bean instance created by the FactoryBean isSingleton or Prototype;

  • Class

    getObjectType() : Returns the Bean type created by FactoryBean.

When the implementation class of

in the configuration file is FactoryBean, the getBean() method returns not the FactoryBean itself, but the object returned by the FactoryBean#getObject() method. The equivalent of FactoryBean#getObject() proxies the getBean() method.

For example, if the

of a Car is configured in the traditional way, each property of the Car corresponds to a element tag.

package  com.baobaotao.factorybean;  
    public   class  Car  {  
        private   int maxSpeed ;  
        private  String brand ;  
        private   double price ;  
        public   int  getMaxSpeed ()   {  
            return   this . maxSpeed ;  
        }  
        public   void  setMaxSpeed ( int  maxSpeed )   {  
            this . maxSpeed  = maxSpeed;  
        }  
        public  String getBrand ()   {  
            return   this . brand ;  
        }  
        public   void  setBrand ( String brand )   {  
            this . brand  = brand;  
        }  
        public   double  getPrice ()   {  
            return   this . price ;  
        }  
        public   void  setPrice ( double price ) { this . price = price; }}Copy the code

If implemented as a FactoryBean, the following example uses a comma separator to specify configuration values for all attributes of Car at once:

package  com.baobaotao.factorybean;  
import  org.springframework.beans.factory.FactoryBean;  
public   class  CarFactoryBean  implements  FactoryBean<Car>  {  
    private  String carInfo ;  
    public  Car getObject ()   throws  Exception  {  
        Car car =  new  Car () ;  
        String []  infos =  carInfo .split ( ","); car.setBrand ( infos [ 0 ]) ; car.setMaxSpeed ( Integer. valueOf ( infos [ 1 ])) ; car.setPrice ( Double. valueOf ( infos [ 2 ])) ;return  car;  
    }  
    public  Class<Car> getObjectType ()   {  
        return  Car. class ;  
    }  
    public   boolean  isSingleton ()   {  
        return   false ;  
    }  
    public  String getCarInfo ()   {  
        returnthis . carInfo ; } // Accept a comma separator to set property information public voidsetCarInfo ( String carInfo ) { this . carInfo = carInfo; }}Copy the code

Once you have the CarFactoryBean, you can configure the CarBean in your configuration file using the following custom configuration:

<bean d="car"class="com.baobaotao.factorybean.CarFactoryBean"
P:carInfo="Ferrari,400,2000 million"/>
Copy the code

When getBean(“car”) is called and Spring discovers through reflection that The CarFactoryBean implements the Interface to the FactoryBean, the Spring container calls the interface method CarFactoryBean#getObject() to return. If you want to get an instance of CarFactoryBean, you need to prefix beanName with “&” when using getBean(beanName) : getBean(“&car”);

Here is an example of applying FactoryBean

<beans xmlns="http://www.springframework.org/schema/beans"  
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
             xmlns:context="http://www.springframework.org/schema/context"  
             xmlns:aop="http://www.springframework.org/schema/aop"  
             xmlns:tx="http://www.springframework.org/schema/tx"  
             xsi:schemaLocation="Http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">  

 <bean id="student" class="com.spring.bean.Student">    
  <property name="name" value="zhangsan" />    
 </bean>    

 <bean id="school" class="com.spring.bean.School">    
 </bean>   

 <bean id="factoryBeanPojo" class="com.spring.bean.FactoryBeanPojo">    
    <property name="type" value="student" />  
 </bean>   
</beans>
Copy the code

The implementation class of a FactoryBean

import org.springframework.beans.factory.FactoryBean; /** * @author Author wangbiao * @parameter * @return  
 */  
public class FactoryBeanPojo implements FactoryBean{  
    private String type;  

    @Override  
    public Object getObject() throws Exception {  
        if("student".equals(type)) {return new Student();             
        }else{  
            return new School();  
        }  

    }  

    @Override  
    public Class getObjectType() {  
        return School.class;  
    }  

    @Override  
    public boolean isSingleton() {  
        return true;  
    }  

    public String getType() {  
        return type;  
    }  

    public void setType(String type) {  
        this.type = type; }}Copy the code

The common bean

/** * @author Author wangbiao * @parameter * @return  
 */  
public class School {  
    private String schoolName;  
    private String address;  
    private int studentNumber;  
    public String getSchoolName() {  
        return schoolName;  
    }  
    public void setSchoolName(String schoolName) {  
        this.schoolName = schoolName;  
    }  
    public String getAddress() {  
        return address;  
    }  
    public void setAddress(String address) {  
        this.address = address;  
    }  
    public int getStudentNumber() {  
        return studentNumber;  
    }  
    public void setStudentNumber(int studentNumber) {  
        this.studentNumber = studentNumber;  
    }  
    @Override  
    public String toString() {  
        return "School [schoolName=" + schoolName + ", address=" + address  
                + ", studentNumber=" + studentNumber + "]"; }}Copy the code

The test class

import org.springframework.context.support.ClassPathXmlApplicationContext; import com.spring.bean.FactoryBeanPojo; /** * @author Author wangbiao * @parameter * @return  
 */  
public class FactoryBeanTest {  
    public static void main(String[] args){  
        String url = "com/spring/config/BeanConfig.xml";  
        ClassPathXmlApplicationContext cpxa = new ClassPathXmlApplicationContext(url);  
        Object school=  cpxa.getBean("factoryBeanPojo");  
        FactoryBeanPojo factoryBeanPojo= (FactoryBeanPojo) cpxa.getBean("&factoryBeanPojo"); System.out.println(school.getClass().getName()); System.out.println(factoryBeanPojo.getClass().getName()); }}Copy the code

Output results:

November 16, 2016 10:28:24 morning org. Springframework. Context. Support. AbstractApplicationContext prepareRefresh INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1e8ee5c0: startup date [Wed Nov 16 10:28:24 CST 2016]; Root of Context Hierarchy November 16, 2016 10:28:24 morning org. Springframework. Beans. Factory. XML. XmlBeanDefinitionReader loadBeanDefinitions INFO: Loading XML bean definitions from the class path resource [com/spring/config/BeanConfig XML] on November 16, 2016 10:28:24 morning org. Springframework. Beans. Factory. Support. DefaultListableBeanFactory preInstantiateSingletons INFO: Pre-instantiating singletonsin org.springframework.beans.factory.support.DefaultListableBeanFactory@35b793ee: defining beans [student,school,factoryBeanPojo]; root of factory hierarchy  
com.spring.bean.Student  
com.spring.bean.FactoryBeanPojo
Copy the code

As you can see from the result, when retrieving the FactoryBeanPojo object from the IOC container, use getBean(String BeanName) to get the Student object. You can see that when the Type attribute in FactoryBeanPojo is set to student, the student object is returned in the getObject() method.

So when we get the implementation class of a FactoryBean from the IOC container, we get the object returned by the getObject method in the implementation class. To get the implementation class of a FactoryBean, GetBean (String &BeanName) is written as getBean(String &BeanName) after the BeanName in getBean(String BeanName).

reference

https://blog.csdn.net/wangbiao007/article/details/53183764

https://blog.csdn.net/qiesheng/article/details/72875315

https://www.cnblogs.com/redcool/p/6413461.html

The last

Welcome to pay attention to the public number: programmer chasing wind, reply 66, get a 300 page PDF document Java core knowledge summary!

These are some of the things that the interviewer should ask during the interview. These include basics, Java collections, JVMS, multi-threaded concurrency, Spring principles, microservices, Netty and RPC, Kafka, diaries, design patterns, Java algorithms, databases, Zookeeper, distributed caching, data structures, and more.