Java编程之创建对象——Objenesis简单使用

一、背景

最近在研读Spring的官方文档,当在对照Spring源码时,发现了Objenesis的字样,于是谈谈究竟:

package org.springframework.aop.framework;

import java.lang.reflect.Constructor;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.Factory;
import org.springframework.objenesis.SpringObjenesis;
import org.springframework.util.ReflectionUtils;

/**
 * Objenesis-based extension of {@link CglibAopProxy} to create proxy instances
 * without invoking the constructor of the class. Used by default as of Spring 4.
 *
 * @author Oliver Gierke
 * @author Juergen Hoeller
 * @since 4.0
 */
@SuppressWarnings("serial")
class ObjenesisCglibAopProxy extends CglibAopProxy {

	private static final Log logger = LogFactory.getLog(ObjenesisCglibAopProxy.class);

	private static final SpringObjenesis objenesis = new SpringObjenesis();


	/**
	 * Create a new ObjenesisCglibAopProxy for the given AOP configuration.
	 * @param config the AOP configuration as AdvisedSupport object
	 */
	public ObjenesisCglibAopProxy(AdvisedSupport config) {
		super(config);
	}


	@Override
	protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
		Class<?> proxyClass = enhancer.createClass();
		Object proxyInstance = null;

		if (objenesis.isWorthTrying()) {
			try {
				proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());
			}
			catch (Throwable ex) {
				logger.debug("Unable to instantiate proxy using Objenesis, " +
						"falling back to regular proxy construction", ex);
			}
		}

		if (proxyInstance == null) {
			// Regular instantiation via default constructor...
			try {
				Constructor<?> ctor = (this.constructorArgs != null ?
						proxyClass.getDeclaredConstructor(this.constructorArgTypes) :
						proxyClass.getDeclaredConstructor());
				ReflectionUtils.makeAccessible(ctor);
				proxyInstance = (this.constructorArgs != null ?
						ctor.newInstance(this.constructorArgs) : ctor.newInstance());
			}
			catch (Throwable ex) {
				throw new AopConfigException("Unable to instantiate proxy using Objenesis, " +
						"and regular proxy instantiation via default constructor fails as well", ex);
			}
		}

		((Factory) proxyInstance).setCallbacks(callbacks);
		return proxyInstance;
	}

}

二、objenesis简介

1、简介

objenesis是一个小型java类库用来实例化一个特定class的对象。

2、使用场合

Java已经支持使用Class.newInstance()动态实例化类的实例。但是类必须拥有一个合适的构造器。有很多场景下不能使用这种方式实例化类,比如:

  • 构造器需要参数

  • 构造器有side effects

  • 构造器会抛异常

因此,在类库中经常会有类必须拥有一个默认构造器的限制。Objenesis通过绕开对象实例构造器来克服这个限制。

3、典型使用

实例化一个对象而不调用构造器是一个特殊的任务,然而在一些特定的场合是有用的:

  • 序列化,远程调用和持久化 -对象需要实例化并存储为到一个特殊的状态,而没有调用代码。

  • 代理,AOP库和Mock对象 -类可以被子类继承而子类不用担心父类的构造器

  • 容器框架 -对象可以以非标准的方式被动态实例化。

三、objenesis示例

1、在pom.xml中引入依赖

		<!-- https://mvnrepository.com/artifact/org.objenesis/objenesis -->
		<dependency>
			<groupId>org.objenesis</groupId>
			<artifactId>objenesis</artifactId>
			<version>3.0.1</version>
		</dependency>

2、示例代码如下

package io.gitee.inrgihc.objenesis;

import org.objenesis.Objenesis;
import org.objenesis.ObjenesisStd;
import org.objenesis.instantiator.ObjectInstantiator;

class Person {

	{
		System.out.println("In Person instance function");
	}

	public Person() {
		System.out.println("In Person constructor function");
		throw new RuntimeException("constructor can not used!");
	}

	public void show() {
		System.out.println("Person show() function called!" + this.hashCode());
	}
}

public class Application {

	public static void main(String[] args) {
		Objenesis objenesis = new ObjenesisStd();
		ObjectInstantiator<Person> instantiator = objenesis.getInstantiatorOf(Person.class);
		Person p1 = instantiator.newInstance();
		p1.show();
		Person p2 = instantiator.newInstance();
		p2.show();
	}

}

运行结果:

Person show() function called!312714112
Person show() function called!692404036

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值