类org.hibernate.proxy.LazyInitializer源码实例Demo

下面列出了怎么用org.hibernate.proxy.LazyInitializer的API类实例代码及写法,或者点击链接到github查看源代码。

源代码1 项目: lams   文件: PersistenceUtilHelper.java
/**
 * Is the given attribute (by name) loaded?  This form must take care to not access the attribute (trigger
 * initialization).
 *
 * @param entity The entity
 * @param attributeName The name of the attribute to check
 * @param cache The cache we maintain of attribute resolutions
 *
 * @return The LoadState
 */
public static LoadState isLoadedWithReference(Object entity, String attributeName, MetadataCache cache) {
	if ( entity instanceof HibernateProxy ) {
		final LazyInitializer li = ( (HibernateProxy) entity ).getHibernateLazyInitializer();
		if ( li.isUninitialized() ) {
			// we have an uninitialized proxy, the attribute cannot be loaded
			return LoadState.NOT_LOADED;
		}
		else {
			// swap the proxy with target (for proper class name resolution)
			entity = li.getImplementation();
		}
	}

	try {
		final Class entityClass = entity.getClass();
		final Object attributeValue = cache.getClassMetadata( entityClass )
				.getAttributeAccess( attributeName )
				.extractValue( entity );
		return isLoaded( attributeValue );
	}
	catch (AttributeExtractionException ignore) {
		return LoadState.UNKNOWN;
	}
}
 
源代码2 项目: lams   文件: StatefulPersistenceContext.java
@Override
public Object unproxy(Object maybeProxy) throws HibernateException {
	if ( maybeProxy instanceof HibernateProxy ) {
		final HibernateProxy proxy = (HibernateProxy) maybeProxy;
		final LazyInitializer li = proxy.getHibernateLazyInitializer();
		if ( li.isUninitialized() ) {
			throw new PersistentObjectException(
					"object was an uninitialized proxy for " + li.getEntityName()
			);
		}
		//unwrap the object and return
		return li.getImplementation();
	}
	else {
		return maybeProxy;
	}
}
 
源代码3 项目: lams   文件: Hibernate.java
/**
 * Check if the property is initialized. If the named property does not exist
 * or is not persistent, this method always returns <tt>true</tt>.
 *
 * @param proxy The potential proxy
 * @param propertyName the name of a persistent attribute of the object
 * @return true if the named property of the object is not listed as uninitialized; false otherwise
 */
public static boolean isPropertyInitialized(Object proxy, String propertyName) {
	final Object entity;
	if ( proxy instanceof HibernateProxy ) {
		final LazyInitializer li = ( (HibernateProxy) proxy ).getHibernateLazyInitializer();
		if ( li.isUninitialized() ) {
			return false;
		}
		else {
			entity = li.getImplementation();
		}
	}
	else {
		entity = proxy;
	}

	if ( entity instanceof PersistentAttributeInterceptable ) {
		PersistentAttributeInterceptor interceptor = ( (PersistentAttributeInterceptable) entity ).$$_hibernate_getInterceptor();
		if ( interceptor != null && interceptor instanceof LazyAttributeLoadingInterceptor ) {
			return ( (LazyAttributeLoadingInterceptor) interceptor ).isAttributeLoaded( propertyName );
		}
	}

	return true;
}
 
源代码4 项目: lams   文件: SessionImpl.java
@Override
public Serializable getIdentifier(Object object) throws HibernateException {
	checkOpen();
	checkTransactionSynchStatus();
	if ( object instanceof HibernateProxy ) {
		LazyInitializer li = ( (HibernateProxy) object ).getHibernateLazyInitializer();
		if ( li.getSession() != this ) {
			throw new TransientObjectException( "The proxy was not associated with this session" );
		}
		return li.getIdentifier();
	}
	else {
		EntityEntry entry = persistenceContext.getEntry( object );
		if ( entry == null ) {
			throw new TransientObjectException( "The instance was not associated with this session" );
		}
		return entry.getId();
	}
}
 
源代码5 项目: lams   文件: SessionImpl.java
@Override
public String bestGuessEntityName(Object object) {
	if ( object instanceof HibernateProxy ) {
		LazyInitializer initializer = ( (HibernateProxy) object ).getHibernateLazyInitializer();
		// it is possible for this method to be called during flush processing,
		// so make certain that we do not accidentally initialize an uninitialized proxy
		if ( initializer.isUninitialized() ) {
			return initializer.getEntityName();
		}
		object = initializer.getImplementation();
	}
	EntityEntry entry = persistenceContext.getEntry( object );
	if ( entry == null ) {
		return guessEntityName( object );
	}
	else {
		return entry.getPersister().getEntityName();
	}
}
 
源代码6 项目: lams   文件: CollectionType.java
public boolean contains(Object collection, Object childObject, SharedSessionContractImplementor session) {
	// we do not have to worry about queued additions to uninitialized
	// collections, since they can only occur for inverse collections!
	Iterator elems = getElementsIterator( collection, session );
	while ( elems.hasNext() ) {
		Object element = elems.next();
		// worrying about proxies is perhaps a little bit of overkill here...
		if ( element instanceof HibernateProxy ) {
			LazyInitializer li = ( (HibernateProxy) element ).getHibernateLazyInitializer();
			if ( !li.isUninitialized() ) {
				element = li.getImplementation();
			}
		}
		if ( element == childObject ) {
			return true;
		}
	}
	return false;
}
 
/**
 * Takes the given object and, if it represents a proxy, reassociates it with this event source.
 *
 * @param value The possible proxy to be reassociated.
 * @return Whether the passed value represented an actual proxy which got initialized.
 * @throws MappingException
 */
public boolean reassociateIfUninitializedProxy(Object value) throws MappingException {
	if ( value instanceof ElementWrapper ) {
		value = ( (ElementWrapper) value ).getElement();
	}
	
	if ( !Hibernate.isInitialized(value) ) {
		HibernateProxy proxy = (HibernateProxy) value;
		LazyInitializer li = proxy.getHibernateLazyInitializer();
		reassociateProxy(li, proxy);
		return true;
	}
	else {
		return false;
	}
}
 
/**
 * Get the entity instance underlying the given proxy, throwing
 * an exception if the proxy is uninitialized. If the given object
 * is not a proxy, simply return the argument.
 */
public Object unproxy(Object maybeProxy) throws HibernateException {
	if ( maybeProxy instanceof ElementWrapper ) {
		maybeProxy = ( (ElementWrapper) maybeProxy ).getElement();
	}
	
	if ( maybeProxy instanceof HibernateProxy ) {
		HibernateProxy proxy = (HibernateProxy) maybeProxy;
		LazyInitializer li = proxy.getHibernateLazyInitializer();
		if ( li.isUninitialized() ) {
			throw new PersistentObjectException(
					"object was an uninitialized proxy for " +
					li.getEntityName()
			);
		}
		return li.getImplementation(); //unwrap the object
	}
	else {
		return maybeProxy;
	}
}
 
/**
 * Possibly unproxy the given reference and reassociate it with the current session.
 *
 * @param maybeProxy The reference to be unproxied if it currently represents a proxy.
 * @return The unproxied instance.
 * @throws HibernateException
 */
public Object unproxyAndReassociate(Object maybeProxy) throws HibernateException {
	if ( maybeProxy instanceof ElementWrapper ) {
		maybeProxy = ( (ElementWrapper) maybeProxy ).getElement();
	}
	
	if ( maybeProxy instanceof HibernateProxy ) {
		HibernateProxy proxy = (HibernateProxy) maybeProxy;
		LazyInitializer li = proxy.getHibernateLazyInitializer();
		reassociateProxy(li, proxy);
		return li.getImplementation(); //initialize + unwrap the object
	}
	else {
		return maybeProxy;
	}
}
 
源代码10 项目: cacheonix-core   文件: Hibernate.java
/**
 * Check if the property is initialized. If the named property does not exist
 * or is not persistent, this method always returns <tt>true</tt>.
 *
 * @param proxy The potential proxy
 * @param propertyName the name of a persistent attribute of the object
 * @return true if the named property of the object is not listed as uninitialized
 * @return false if the object is an uninitialized proxy, or the named property is uninitialized
 */
public static boolean isPropertyInitialized(Object proxy, String propertyName) {
	
	Object entity;
	if ( proxy instanceof HibernateProxy ) {
		LazyInitializer li = ( ( HibernateProxy ) proxy ).getHibernateLazyInitializer();
		if ( li.isUninitialized() ) {
			return false;
		}
		else {
			entity = li.getImplementation();
		}
	}
	else {
		entity = proxy;
	}

	if ( FieldInterceptionHelper.isInstrumented( entity ) ) {
		FieldInterceptor interceptor = FieldInterceptionHelper.extractFieldInterceptor( entity );
		return interceptor == null || interceptor.isInitialized( propertyName );
	}
	else {
		return true;
	}
	
}
 
源代码11 项目: cacheonix-core   文件: DefaultLoadEventListener.java
/**
 * Given that there is a pre-existing proxy.
 * Initialize it if necessary; narrow if necessary.
 */
private Object returnNarrowedProxy(
		final LoadEvent event, 
		final EntityPersister persister, 
		final EntityKey keyToLoad, 
		final LoadEventListener.LoadType options, 
		final PersistenceContext persistenceContext, 
		final Object proxy
) {
	log.trace("entity proxy found in session cache");
	LazyInitializer li = ( (HibernateProxy) proxy ).getHibernateLazyInitializer();
	if ( li.isUnwrap() ) {
		return li.getImplementation();
	}
	Object impl = null;
	if ( !options.isAllowProxyCreation() ) {
		impl = load( event, persister, keyToLoad, options );
		if ( impl == null ) {
			event.getSession().getFactory().getEntityNotFoundDelegate().handleEntityNotFound( persister.getEntityName(), keyToLoad.getIdentifier());
		}
	}
	return persistenceContext.narrowProxy( proxy, persister, keyToLoad, impl );
}
 
源代码12 项目: cacheonix-core   文件: SessionImpl.java
public Serializable getIdentifier(Object object) throws HibernateException {
	errorIfClosed();
	checkTransactionSynchStatus();
	if ( object instanceof HibernateProxy ) {
		LazyInitializer li = ( (HibernateProxy) object ).getHibernateLazyInitializer();
		if ( li.getSession() != this ) {
			throw new TransientObjectException( "The proxy was not associated with this session" );
		}
		return li.getIdentifier();
	}
	else {
		EntityEntry entry = persistenceContext.getEntry(object);
		if ( entry == null ) {
			throw new TransientObjectException( "The instance was not associated with this session" );
		}
		return entry.getId();
	}
}
 
源代码13 项目: cacheonix-core   文件: SessionImpl.java
public String bestGuessEntityName(Object object) {
	if (object instanceof HibernateProxy) {
		LazyInitializer initializer = ( ( HibernateProxy ) object ).getHibernateLazyInitializer();
		// it is possible for this method to be called during flush processing,
		// so make certain that we do not accidently initialize an uninitialized proxy
		if ( initializer.isUninitialized() ) {
			return initializer.getEntityName();
		}
		object = initializer.getImplementation();
	}
	EntityEntry entry = persistenceContext.getEntry(object);
	if (entry==null) {
		return guessEntityName(object);
	}
	else {
		return entry.getPersister().getEntityName();
	}
}
 
源代码14 项目: hibernate-reactive   文件: ReactiveSessionImpl.java
@Override
public <T> CompletionStage<T> reactiveFetch(T association, boolean unproxy) {
	checkOpen();
	if ( association instanceof HibernateProxy ) {
		LazyInitializer initializer = ((HibernateProxy) association).getHibernateLazyInitializer();
		//TODO: is this correct?
		// SessionImpl doesn't use IdentifierLoadAccessImpl for initializing proxies
		String entityName = initializer.getEntityName();
		Serializable identifier = initializer.getIdentifier();
		return new ReactiveIdentifierLoadAccessImpl<T>( entityName )
				.fetch( identifier )
				.thenApply( SessionUtil.checkEntityFound( this, entityName, identifier ) )
				.thenApply( entity -> {
					initializer.setSession( this );
					initializer.setImplementation( entity );
					return unproxy ? entity : association;
				} );
	}
	else if ( association instanceof PersistentCollection ) {
		PersistentCollection persistentCollection = (PersistentCollection) association;
		return reactiveInitializeCollection( persistentCollection, false )
				.thenApply( pc -> association );
	}
	else {
		return CompletionStages.completedFuture( association );
	}
}
 
/**
 * Given a proxy, initialize it and/or narrow it provided either
 * is necessary.
 *
 * @param event The initiating load request event
 * @param persister The persister corresponding to the entity to be loaded
 * @param keyToLoad The key of the entity to be loaded
 * @param options The defined load options
 * @param persistenceContext The originating session
 * @param proxy The proxy to narrow
 *
 * @return The created/existing proxy
 */
private CompletionStage<Object> returnNarrowedProxy(
		final LoadEvent event,
		final EntityPersister persister,
		final EntityKey keyToLoad,
		final LoadEventListener.LoadType options,
		final PersistenceContext persistenceContext,
		final Object proxy) {
	if ( LOG.isTraceEnabled() ) {
		LOG.trace( "Entity proxy found in session cache" );
	}

	LazyInitializer li = ( (HibernateProxy) proxy ).getHibernateLazyInitializer();

	if ( li.isUnwrap() ) {
		return CompletionStages.completedFuture( li.getImplementation() );
	}

	CompletionStage<Object> implStage;
	if ( !options.isAllowProxyCreation() ) {
		implStage = load( event, persister, keyToLoad, options )
				.thenApply( optional -> {
					if ( optional == null ) {
						event.getSession()
								.getFactory()
								.getEntityNotFoundDelegate()
								.handleEntityNotFound( persister.getEntityName(), keyToLoad.getIdentifier() );
					}
					return optional;
				} );
	}
	else {
		implStage = CompletionStages.nullFuture();
	}

	return implStage.thenApply( impl -> persistenceContext.narrowProxy( proxy, persister, keyToLoad, impl ) );
}
 
源代码16 项目: lams   文件: StatefulPersistenceContext.java
@Override
public boolean reassociateIfUninitializedProxy(Object value) throws MappingException {
	if ( !Hibernate.isInitialized( value ) ) {
		final HibernateProxy proxy = (HibernateProxy) value;
		final LazyInitializer li = proxy.getHibernateLazyInitializer();
		reassociateProxy( li, proxy );
		return true;
	}
	else {
		return false;
	}
}
 
源代码17 项目: lams   文件: StatefulPersistenceContext.java
@Override
public void reassociateProxy(Object value, Serializable id) throws MappingException {
	if ( value instanceof HibernateProxy ) {
		LOG.debugf( "Setting proxy identifier: %s", id );
		final HibernateProxy proxy = (HibernateProxy) value;
		final LazyInitializer li = proxy.getHibernateLazyInitializer();
		li.setIdentifier( id );
		reassociateProxy( li, proxy );
	}
}
 
源代码18 项目: lams   文件: StatefulPersistenceContext.java
/**
 * Associate a proxy that was instantiated by another session with this session
 *
 * @param li The proxy initializer.
 * @param proxy The proxy to reassociate.
 */
private void reassociateProxy(LazyInitializer li, HibernateProxy proxy) {
	if ( li.getSession() != this.getSession() ) {
		final EntityPersister persister = session.getFactory().getMetamodel().entityPersister( li.getEntityName() );
		final EntityKey key = session.generateEntityKey( li.getIdentifier(), persister );
	  	// any earlier proxy takes precedence
		proxiesByKey.putIfAbsent( key, proxy );
		proxy.getHibernateLazyInitializer().setSession( session );
	}
}
 
源代码19 项目: lams   文件: StatefulPersistenceContext.java
@Override
public Object unproxyAndReassociate(Object maybeProxy) throws HibernateException {
	if ( maybeProxy instanceof HibernateProxy ) {
		final HibernateProxy proxy = (HibernateProxy) maybeProxy;
		final LazyInitializer li = proxy.getHibernateLazyInitializer();
		reassociateProxy( li, proxy );
		//initialize + unwrap the object and return it
		return li.getImplementation();
	}
	else {
		return maybeProxy;
	}
}
 
源代码20 项目: lams   文件: Hibernate.java
/**
    * Unproxies a {@link HibernateProxy}. If the proxy is uninitialized, it automatically triggers an initialization.
    * In case the supplied object is null or not a proxy, the object will be returned as-is.
    *
    * @param proxy the {@link HibernateProxy} to be unproxied
    * @return the proxy's underlying implementation object, or the supplied object otherwise
    */
public static Object unproxy(Object proxy) {
	if ( proxy instanceof HibernateProxy ) {
		HibernateProxy hibernateProxy = (HibernateProxy) proxy;
		LazyInitializer initializer = hibernateProxy.getHibernateLazyInitializer();
		return initializer.getImplementation();
	}
	else {
		return proxy;
	}
}
 
源代码21 项目: lams   文件: DefaultLoadEventListener.java
/**
 * Given a proxy, initialize it and/or narrow it provided either
 * is necessary.
 *
 * @param event The initiating load request event
 * @param persister The persister corresponding to the entity to be loaded
 * @param keyToLoad The key of the entity to be loaded
 * @param options The defined load options
 * @param persistenceContext The originating session
 * @param proxy The proxy to narrow
 *
 * @return The created/existing proxy
 */
private Object returnNarrowedProxy(
		final LoadEvent event,
		final EntityPersister persister,
		final EntityKey keyToLoad,
		final LoadEventListener.LoadType options,
		final PersistenceContext persistenceContext,
		final Object proxy) {
	if ( traceEnabled ) {
		LOG.trace( "Entity proxy found in session cache" );
	}
	LazyInitializer li = ( (HibernateProxy) proxy ).getHibernateLazyInitializer();
	if ( li.isUnwrap() ) {
		return li.getImplementation();
	}
	Object impl = null;
	if ( !options.isAllowProxyCreation() ) {
		impl = load( event, persister, keyToLoad, options );
		if ( impl == null ) {
			event.getSession()
					.getFactory()
					.getEntityNotFoundDelegate()
					.handleEntityNotFound( persister.getEntityName(), keyToLoad.getIdentifier() );
		}
	}
	return persistenceContext.narrowProxy( proxy, persister, keyToLoad, impl );
}
 
源代码22 项目: lams   文件: AnyType.java
private EntityPersister guessEntityPersister(Object object) {
	if ( scope == null ) {
		return null;
	}

	String entityName = null;

	// this code is largely copied from Session's bestGuessEntityName
	Object entity = object;
	if ( entity instanceof HibernateProxy ) {
		final LazyInitializer initializer = ( (HibernateProxy) entity ).getHibernateLazyInitializer();
		if ( initializer.isUninitialized() ) {
			entityName = initializer.getEntityName();
		}
		entity = initializer.getImplementation();
	}

	if ( entityName == null ) {
		for ( EntityNameResolver resolver : scope.getTypeConfiguration().getSessionFactory().getMetamodel().getEntityNameResolvers() ) {
			entityName = resolver.resolveEntityName( entity );
			if ( entityName != null ) {
				break;
			}
		}
	}

	if ( entityName == null ) {
		// the old-time stand-by...
		entityName = object.getClass().getName();
	}

	return scope.getTypeConfiguration().getSessionFactory().getMetamodel().entityPersister( entityName );
}
 
public Object unwrapProxy(final HibernateProxy proxy) {
    final LazyInitializer lazyInitializer = proxy.getHibernateLazyInitializer();
    if (lazyInitializer.isUninitialized()) {
        lazyInitializer.initialize();
    }
    final Object obj = lazyInitializer.getImplementation();
    if (obj != null) {
        ensureCorrectGroovyMetaClass(obj, obj.getClass());
    }
    return obj;
}
 
public void initialize(Object o) {
    if (o instanceof HibernateProxy) {
        final LazyInitializer hibernateLazyInitializer = ((HibernateProxy)o).getHibernateLazyInitializer();
        if (hibernateLazyInitializer.isUninitialized()) {
            hibernateLazyInitializer.initialize();
        }
    }
    else {
        super.initialize(o);
    }
}
 
public void clear() {
	Iterator itr = proxiesByKey.values().iterator();
	while ( itr.hasNext() ) {
		final LazyInitializer li = ( ( HibernateProxy ) itr.next() ).getHibernateLazyInitializer();
		li.setSession( null );
	}
	Map.Entry[] collectionEntryArray = IdentityMap.concurrentEntries( collectionEntries );
	for ( int i = 0; i < collectionEntryArray.length; i++ ) {
		( ( PersistentCollection ) collectionEntryArray[i].getKey() ).unsetSession( getSession() );
	}
	arrayHolders.clear();
	entitiesByKey.clear();
	entitiesByUniqueKey.clear();
	entityEntries.clear();
	entitySnapshotsByKey.clear();
	collectionsByKey.clear();
	collectionEntries.clear();
	if ( unownedCollections != null ) {
		unownedCollections.clear();
	}
	proxiesByKey.clear();
	nullifiableEntityKeys.clear();
	if ( batchFetchQueue != null ) {
		batchFetchQueue.clear();
	}
	hasNonReadOnlyEntities = false;
	if ( loadContexts != null ) {
		loadContexts.cleanup();
	}
}
 
/**
 * If a deleted entity instance is re-saved, and it has a proxy, we need to
 * reset the identifier of the proxy 
 */
public void reassociateProxy(Object value, Serializable id) throws MappingException {
	if ( value instanceof ElementWrapper ) {
		value = ( (ElementWrapper) value ).getElement();
	}
	
	if ( value instanceof HibernateProxy ) {
		if ( log.isDebugEnabled() ) log.debug("setting proxy identifier: " + id);
		HibernateProxy proxy = (HibernateProxy) value;
		LazyInitializer li = proxy.getHibernateLazyInitializer();
		li.setIdentifier(id);
		reassociateProxy(li, proxy);
	}
}
 
/**
 * Associate a proxy that was instantiated by another session with this session
 *
 * @param li The proxy initializer.
 * @param proxy The proxy to reassociate.
 */
private void reassociateProxy(LazyInitializer li, HibernateProxy proxy) {
	if ( li.getSession() != this.getSession() ) {
		EntityPersister persister = session.getFactory().getEntityPersister( li.getEntityName() );
		EntityKey key = new EntityKey( li.getIdentifier(), persister, session.getEntityMode() );
	  	// any earlier proxy takes precedence
		if ( !proxiesByKey.containsKey( key ) ) {
			proxiesByKey.put( key, proxy );
		}
		proxy.getHibernateLazyInitializer().setSession( session );
	}
}
 
/**
 * If the existing proxy is insufficiently "narrow" (derived), instantiate a new proxy
 * and overwrite the registration of the old one. This breaks == and occurs only for
 * "class" proxies rather than "interface" proxies. Also init the proxy to point to
 * the given target implementation if necessary.
 *
 * @param proxy The proxy instance to be narrowed.
 * @param persister The persister for the proxied entity.
 * @param key The internal cache key for the proxied entity.
 * @param object (optional) the actual proxied entity instance.
 * @return An appropriately narrowed instance.
 * @throws HibernateException
 */
public Object narrowProxy(Object proxy, EntityPersister persister, EntityKey key, Object object)
throws HibernateException {
	
	boolean alreadyNarrow = persister.getConcreteProxyClass( session.getEntityMode() )
			.isAssignableFrom( proxy.getClass() );
	
	if ( !alreadyNarrow ) {
		if ( PROXY_WARN_LOG.isWarnEnabled() ) {
			PROXY_WARN_LOG.warn(
					"Narrowing proxy to " +
					persister.getConcreteProxyClass( session.getEntityMode() ) +
					" - this operation breaks =="
			);
		}

		if ( object != null ) {
			proxiesByKey.remove(key);
			return object; //return the proxied object
		}
		else {
			proxy = persister.createProxy( key.getIdentifier(), session );
			proxiesByKey.put(key, proxy); //overwrite old proxy
			return proxy;
		}
		
	}
	else {
		
		if ( object != null ) {
			LazyInitializer li = ( (HibernateProxy) proxy ).getHibernateLazyInitializer();
			li.setImplementation(object);
		}
		
		return proxy;
		
	}
	
}
 
源代码29 项目: cacheonix-core   文件: FieldInterceptorImpl.java
public Object readObject(Object target, String name, Object oldValue) {
	Object value = intercept( target, name, oldValue );
	if (value instanceof HibernateProxy) {
		LazyInitializer li = ( (HibernateProxy) value ).getHibernateLazyInitializer();
		if ( li.isUnwrap() ) {
			value = li.getImplementation();
		}
	}
	return value;
}
 
源代码30 项目: cacheonix-core   文件: FieldInterceptorImpl.java
public Object readObject(Object target, String name, Object oldValue) {
	Object value = intercept( target, name, oldValue );
	if (value instanceof HibernateProxy) {
		LazyInitializer li = ( (HibernateProxy) value ).getHibernateLazyInitializer();
		if ( li.isUnwrap() ) {
			value = li.getImplementation();
		}
	}
	return value;
}
 
 类所在包
 同包方法