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
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.