Spring中创建对象的方式整理
作者:互联网
在没有使用Spring时,开发者创建对象一般都是使用new/反射创建对象;Spring出来后简化了开发方式,它提供了一个IoC容器的实现,用于帮助开发者以依赖注入的方式管理对象之间的依赖关系,从而将开发者创建对象的所有权转移到IoC容器上,这使得Spring易于整合第三方模块,因此Spring更是一个分层的框架;
对于Spring创建对象的方式创建整理如下:
方式一:自定义BeanPostProcessor,生成代理对象
如实现InstantiationAwareBeanPostProcessor接口,其中InstantiationAwareBeanPostProcessor是一个BeanPostProcessor,它可用于处理bean实例创建前后的回调;
测试如下:
@Test public void instantiationAwareBeanPostProcessorTest() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); GenericBeanDefinition definition1 = new GenericBeanDefinition(); definition1.setBeanClass(DemoInstantiationAwareBPP.class); context.registerBeanDefinition("demoInstantiationAwareBPP", definition1); GenericBeanDefinition definition2 = new GenericBeanDefinition(); definition2.setBeanClass(InstantiationDemo.class); context.registerBeanDefinition("instantiationDemo", definition2); context.refresh(); InstantiationDemo bean = context.getBean(InstantiationDemo.class); bean.invoke(); }
public class DemoInstantiationAwareBPP implements InstantiationAwareBeanPostProcessor { private final static Log LOG = LogFactory.getLog(DemoInstantiationAwareBPP.class); @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { LOG.info("beanName:" + beanName + "执行postProcessBeforeInstantiation方法"); // 使用cglib生成代理对象 if (beanClass == InstantiationDemo.class) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(beanClass); enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> { boolean objFlag = method.getDeclaringClass().getName().equals("java.lang.Object"); if (!objFlag) { LOG.info("执行方法" + method + "前"); Object rtn = methodProxy.invokeSuper(o, objects); LOG.info("执行方法" + method + "后"); return rtn; } else { return methodProxy.invokeSuper(o, objects); } }); InstantiationDemo bean = (InstantiationDemo) enhancer.create(); LOG.info("创建代理对象:" + bean); return bean; } return null; } @Override public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { LOG.info("beanName:" + beanName + "执行postProcessAfterInstantiation方法"); return false; } }
public class InstantiationDemo { private final static Log LOG = LogFactory.getLog(InstantiationDemo.class); public void invoke() { LOG.info(this); LOG.info("InstantiationDemo invoke"); } }
注:
MethodProxy#invokeSuper是退出当前interceptor的处理,进入下一个callback处理;
MethodProxy#invoke则会继续回调该方法,如果传递给invoke的obj参数出错容易造成递归调用;
方式二:通过反射创建
AbstractAutowireCapableBeanFactory#doCreateBean为真正创建bean的逻辑,该方法是最复杂的,包含了调用构造函数,给bean的属性赋值,调用bean的初始化操作以及生成代理对象;
该方法会调用AbstractAutowireCapableBeanFactory#createBeanInstance实例化对象,如下图;
AbstractAutowireCapableBeanFactory#createBeanInstance根据@Autowried自动注入/调用无参构造器创建,进行相应的处理;
- instantiateBean 调用无参数的构造器进行创建对象;
- autowireConstructor @Autowired自动注入,调用构造器注入;
方式三:通过FactoryBean创建对象
AbstractBeanFactory#getObjectForBeanInstance
如果有实现了FactoryBean接口的实例,则从FactoryBean中获取实例;
测试如下:
@Test public void mainTest13() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( MainConfig10.class); System.out.println("IOC容器创建完成..."); // 调用FactoryBean#getBean方法,入参为Bean id,得到的对象为FactoryBean#getObjectType的对象 // FactoryBean要获取工厂Bean本身,需要在id前加个& // org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance Object factoryBean1 = context.getBean("demoFactoryBean"); Object factoryBean2 = context.getBean("demoFactoryBean"); System.out.println("factoryBean1==factoryBean2 :" + (factoryBean1 == factoryBean2)); System.out.println("bean的类型:" + factoryBean1.getClass()); Object factoryBean3 = context.getBean("&demoFactoryBean"); System.out.println("bean的类型:" + factoryBean3.getClass()); }
@Configuration public class MainConfig10 { @Bean public DemoFactoryBean demoFactoryBean() { return new DemoFactoryBean(); } }
public class DemoFactoryBean implements FactoryBean<Person> { /** * 是否单例进行控制 * @return */ @Override public boolean isSingleton() { return true; } /** * 返回对象,把对象放到容器中 * @return * @throws Exception */ @Override public Person getObject() throws Exception { return new Person(); } /** * 返回对象类型 * @return */ @Override public Class<?> getObjectType() { return Person.class; } }
方式四:通过设置BeanDefinition属性Supplier创建对象
AbstractAutowireCapableBeanFactory#createBeanInstance
获取bean的supplier;
AbstractAutowireCapableBeanFactory#obtainFromSupplier
通过Suupplier#get方法获取实例,此时获取实例不是使用反射;
测试如下:
@Test public void supplierTest() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); GenericBeanDefinition definition = new GenericBeanDefinition(); definition.setBeanClass(BeanC.class); definition.setInstanceSupplier((Supplier<BeanC>) BeanC::new); context.registerBeanDefinition("beanC", definition); context.refresh(); Assertions.assertNotNull(context.getBean("beanC")); }
public class BeanC { private final static Log LOG = LogFactory.getLog(BeanC.class); public BeanC() { LOG.info("BeanC constructor"); } }
方式五:通过设置BeanDefinition属性factoryMethod创建对象
AbstractAutowireCapableBeanFactory#createBeanInstance
createBeanInstance是实例化对象的过程,如果beanDefinition设置了factoryMethod,则从设置的factoryMethod实例化,而supplier属性的优先级高于factoryMethod,即beanDefinition同时存在supplier和factoryMethod属性时,优先执行supplier的实例化逻辑;
factoryMethod使用方式:往beanDefinition设置factoryMethod所属类的beanName和factoryMethodName的属性;
使用factoryMethod实例化对象的解析逻辑:ConstructorResolver#instantiateUsingFactoryMethod
SimpleInstantiationStrategy最终通过对factoryBean反射调用factoryMethod;
测试如下:
beanDefinition只有factoryMethod属性
public class FactoryDemo { private final static Log LOG = LogFactory.getLog(FactoryDemo.class); private int num; private String msg; public int getNum() { return num; } public void setNum(int num) { this.num = num; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public FactoryDemo() { LOG.info("FactoryDemo no params constructor"); } public BeanDemo create() { BeanDemo beanDemo = new BeanDemo(); LOG.info("invoke create without args,beanDemo:" + beanDemo); return beanDemo; } public BeanDemo create(int num, String msg) { BeanDemo beanDemo = new BeanDemo(); beanDemo.setMsg(msg); beanDemo.setNum(num); LOG.info("invoke create with args,beanDemo:" + "[" + beanDemo + "]" + beanDemo.getMsg() + "," + beanDemo.getNum()); return beanDemo; } }
public class BeanDemo { private final static Log LOG = LogFactory.getLog(BeanDemo.class); private int num; private String msg; public BeanDemo() { LOG.info("BeanDemo constructor"); } public int getNum() { return num; } public void setNum(int num) { this.num = num; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } }
调用无参的factoryMethod
@Test public void factoryBeanNameTestWithoutArgs() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(FactoryDemo.class); GenericBeanDefinition definition = new GenericBeanDefinition(); // 设置factoryBean definition.setFactoryBeanName("factoryDemo"); definition.setFactoryMethodName("create"); definition.setBeanClass(BeanDemo.class); context.registerBeanDefinition("beanDemo", definition); context.refresh(); System.out.println(context.getBean(BeanDemo.class)); }
调用有参factoryMethod
@Test public void factoryBeanNameWithArgsTest() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(FactoryDemo.class); GenericBeanDefinition definition = new GenericBeanDefinition(); // 设置factoryBean definition.setFactoryBeanName("factoryDemo"); definition.setFactoryMethodName("create"); ConstructorArgumentValues argumentValues = new ConstructorArgumentValues(); argumentValues.addGenericArgumentValue("test", "java.lang.String"); argumentValues.addGenericArgumentValue(1, "int"); definition.setConstructorArgumentValues(argumentValues); definition.setBeanClass(BeanDemo.class); context.registerBeanDefinition("beanDemo", definition); context.refresh(); System.out.println(context.getBean(BeanDemo.class)); }
beanDefinition有factoryMethod属性和supplier属性
@Test public void supplierOrderTest() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(FactoryDemo.class); GenericBeanDefinition definition = new GenericBeanDefinition(); // 设置factoryBean definition.setFactoryBeanName("factoryDemo"); definition.setFactoryMethodName("create"); definition.setBeanClass(BeanDemo.class); context.registerBeanDefinition("beanDemo", definition); definition.setInstanceSupplier((Supplier<BeanDemo>) BeanDemo::new); context.refresh(); Assertions.assertNotNull(context.getBean("beanDemo")); }
此时优先执行supplier逻辑;
Spring创建对象方式的整理图
Spring实例化策略整理
标签:definition,return,Spring,创建对象,public,context,整理,new,class 来源: https://www.cnblogs.com/coder-zyc/p/15780169.html