ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Spring中创建对象的方式整理

2022-01-10 01:01:11  阅读:191  来源: 互联网

标签:definition return Spring 创建对象 public context 整理 new class


在没有使用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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有