上篇说到了通过CglibSubclassingInstantiationStrategy类的instantiate方法创建对象实例,然后使用BeanWrapperImpl对象进行包装,初始化后返回。CglibSubclassingInstantiationStrategy类继承自SimpleInstantiationStrategy,而instantiate调用的就是父类SimpleInstantiationStrategy的方法,我们看下源码:
@Override
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
if (bd.getMethodOverrides().isEmpty()) {
Constructor constructorToUse;
synchronized (bd.constructorArgumentLock) {
constructorToUse = (Constructor) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final Class clazz = bd.getBeanClass();
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction>() {
@Override
public Constructor run() throws Exception {
return clazz.getDeclaredConstructor((Class[]) null);
}
});
}
else {
constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Exception ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
然后使用默认构造函数初始化对象,前提是没有methodOvrrides,不需要使用CGLIB动态代理生成子类。
public static T instantiateClass(Constructor ctor, Object... args) throws BeanInstantiationException {
Assert.notNull(ctor, "Constructor must not be null");
try {
ReflectionUtils.makeAccessible(ctor);
return ctor.newInstance(args);
}
catch (InstantiationException ex) {
throw new BeanInstantiationException(ctor.getDeclaringClass(),
"Is it an abstract class?", ex);
}
catch (IllegalAccessException ex) {
throw new BeanInstantiationException(ctor.getDeclaringClass(),
"Is the constructor accessible?", ex);
}
catch (IllegalArgumentException ex) {
throw new BeanInstantiationException(ctor.getDeclaringClass(),
"Illegal arguments for constructor", ex);
}
catch (InvocationTargetException ex) {
throw new BeanInstantiationException(ctor.getDeclaringClass(),
"Constructor threw exception", ex.getTargetException());
}
}
这里也看一下CGLIB的生成代理对象的过程:方法在SimpleInstantiationStrategy的子类CglibSubclassingInstantiationStrategy中被重写得以实现,SimpleInstantiationStrategy内此方法只是抛出了not support的异常。
@Override
protected Object instantiateWithMethodInjection(RootBeanDefinition bd, String beanName, BeanFactory owner) {
return instantiateWithMethodInjection(bd, beanName, owner, null);
}
@Override
protected Object instantiateWithMethodInjection(RootBeanDefinition bd, String beanName, BeanFactory owner,
Constructor ctor, Object... args) {
// Must generate CGLIB subclass...
return new CglibSubclassCreator(bd, owner).instantiate(ctor, args);
}
真正的实现方法在CglibSubclassingInstantiationStrategy的内部类CglibSubclassCreator中,源码如下:
/**
* Create a new instance of a dynamically generated subclass implementing the
* required lookups.
* @param ctor constructor to use. If this is {@code null}, use the
* no-arg constructor (no parameterization, or Setter Injection)
* @param args arguments to use for the constructor.
* Ignored if the {@code ctor} parameter is {@code null}.
* @return new instance of the dynamically generated subclass
*/
public Object instantiate(Constructor ctor, Object... args) {
Class subclass = createEnhancedSubclass(this.beanDefinition);
Object instance;
if (ctor == null) {
instance = BeanUtils.instantiate(subclass);
}
else {
try {
Constructor enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
instance = enhancedSubclassConstructor.newInstance(args);
}
catch (Exception ex) {
throw new BeanInstantiationException(this.beanDefinition.getBeanClass(),
"Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", ex);
}
}
// SPR-10785: set callbacks directly on the instance instead of in the
// enhanced class (via the Enhancer) in order to avoid memory leaks.
Factory factory = (Factory) instance;
factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
return instance;
}
/**
* Create an enhanced subclass of the bean class for the provided bean
* definition, using CGLIB.
*/
private Class createEnhancedSubclass(RootBeanDefinition beanDefinition) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(beanDefinition.getBeanClass());
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition));
enhancer.setCallbackTypes(CALLBACK_TYPES);
return enhancer.createClass();
}
}
从这里可以看出,处理的还是上面我们说到过的两种情况:
private static final Class[] CALLBACK_TYPES = new Class[]
{NoOp.class, LookupOverrideMethodInterceptor.class, ReplaceOverrideMethodInterceptor.class};
言归正传,初始化对象后,我们又回到了AbstractAutowireCapableBeanFactory类的doCreateBean方法,为了方便阅读,再次帖一下这里的源码:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, new ObjectFactory() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set actualDependentBeans = new LinkedHashSet(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
我们获取了wapper之后,先验证此对象是否允许提前曝光,若是的话,则进行一下操作,用以解决循环依赖问题:
/**
* Add the given singleton factory for building the specified singleton
* if necessary.
*
To be called for eager registration of singletons, e.g. to be able to
* resolve circular references.
* @param beanName the name of the bean
* @param singletonFactory the factory for the singleton object
*/
protected void addSingletonFactory(String beanName, ObjectFactory singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
然后开始进行对象的进一步实例化,对象内容填充等操作。
/**
* Populate the bean instance in the given BeanWrapper with the property values
* from the bean definition.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @param bw BeanWrapper with bean instance
*/
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
if (bw == null) {
if (!pvs.isEmpty()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
if (!continueWithPropertyPopulation) {
return;
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
applyPropertyValues(beanName, mbd, bw, pvs);
}
方法开始进行了一些验证后,又再次重复了我们上面谈到的lockup-method等两种情况的处理,若mbd是人工的,且存在响应processors,则进行代理,之后返回,否则,继续进行下一步,然后根据mode决定按名称和或按类型注入。
/**
* Fill in any missing property values with references to
* other beans in this factory if autowire is set to "byName".
* @param beanName the name of the bean we're wiring up.
* Useful for debugging messages; not used functionally.
* @param mbd bean definition to update through autowiring
* @param bw BeanWrapper from which we can obtain information about the bean
* @param pvs the PropertyValues to register wired objects with
*/
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
if (containsBean(propertyName)) {
Object bean = getBean(propertyName);
pvs.add(propertyName, bean);
registerDependentBean(propertyName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("Added autowiring by name from bean name '" + beanName +
"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
"' by name: no matching bean found");
}
}
}
}
/**
* Abstract method defining "autowire by type" (bean properties by type) behavior.
*
This is like PicoContainer default, in which there must be exactly one bean
* of the property type in the bean factory. This makes bean factories simple to
* configure for small namespaces, but doesn't work as well as standard Spring
* behavior for bigger applications.
* @param beanName the name of the bean to autowire by type
* @param mbd the merged bean definition to update through autowiring
* @param bw BeanWrapper from which we can obtain information about the bean
* @param pvs the PropertyValues to register wired objects with
*/
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
Set autowiredBeanNames = new LinkedHashSet(4);
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
// Don't try autowiring by type for type Object: never makes sense,
// even if it technically is a unsatisfied, non-simple property.
if (Object.class != pd.getPropertyType()) {
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
pvs.add(propertyName, autowiredArgument);
}
for (String autowiredBeanName : autowiredBeanNames) {
registerDependentBean(autowiredBeanName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +
propertyName + "' to bean named '" + autowiredBeanName + "'");
}
}
autowiredBeanNames.clear();
}
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}
这里会去先初始化加载依赖的Bean(若Bean尚未初始化)。先说autowirebyName,首先遍历propertyNames,containsBean(propertyName)从单例缓冲或者beanDefinition中查看是否存在指定名称的bean,若存在则调用 Object bean = getBean(propertyName);获取,这里可能会获取已经加载的,若尚未创建则会去加载实例化此对象,然后放到 MutablePropertyValues pvs 以及 registerDependentBean(propertyName, beanName)注册到dependentBeanMap(bean name --> Set of dependent bean names)中去。
对于autowirebyType,首先 MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
获取注入参数的方法,重点看下resolveDependency类型解析方法,
@Override
public Object resolveDependency(DependencyDescriptor descriptor, String beanName,
Set autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (descriptor.getDependencyType().equals(javaUtilOptionalClass)) {
return new OptionalDependencyFactory().createOptionalDependency(descriptor, beanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType()) {
return new DependencyObjectFactory(descriptor, beanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new DependencyProviderFactory().createDependencyProvider(descriptor, beanName);
}
else {
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, beanName);
if (result == null) {
result = doResolveDependency(descriptor, beanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
普通类型的处理在最后一个流程, Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, beanName); if (result == null) { result = doResolveDependency(descriptor, beanName, autowiredBeanNames, typeConverter); } return result;
这里getAutowireCandidateResolver得到SimpleAutowireCandidateResolver,而类中getLazyResolutionProxyIfNecessary(descriptor, beanName);直接返回null,我们看下doResolveDependency方法
public Object doResolveDependency(DependencyDescriptor descriptor, String beanName,
Set autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
Class type = descriptor.getDependencyType();
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
if (type.isArray()) {
Class componentType = type.getComponentType();
DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor);
targetDesc.increaseNestingLevel();
Map matchingBeans = findAutowireCandidates(beanName, componentType, targetDesc);
if (matchingBeans.isEmpty()) {
if (descriptor.isRequired()) {
raiseNoSuchBeanDefinitionException(componentType, "array of " + componentType.getName(), descriptor);
}
return null;
}
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
Object result = converter.convertIfNecessary(matchingBeans.values(), type);
if (getDependencyComparator() != null && result instanceof Object[]) {
Arrays.sort((Object[]) result, adaptDependencyComparator(matchingBeans));
}
return result;
}
else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
Class elementType = descriptor.getCollectionType();
if (elementType == null) {
if (descriptor.isRequired()) {
throw new FatalBeanException("No element type declared for collection [" + type.getName() + "]");
}
return null;
}
DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor);
targetDesc.increaseNestingLevel();
Map matchingBeans = findAutowireCandidates(beanName, elementType, targetDesc);
if (matchingBeans.isEmpty()) {
if (descriptor.isRequired()) {
raiseNoSuchBeanDefinitionException(elementType, "collection of " + elementType.getName(), descriptor);
}
return null;
}
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
Object result = converter.convertIfNecessary(matchingBeans.values(), type);
if (getDependencyComparator() != null && result instanceof List) {
Collections.sort((List) result, adaptDependencyComparator(matchingBeans));
}
return result;
}
else if (Map.class.isAssignableFrom(type) && type.isInterface()) {
Class keyType = descriptor.getMapKeyType();
if (String.class != keyType) {
if (descriptor.isRequired()) {
throw new FatalBeanException("Key type [" + keyType + "] of map [" + type.getName() +
"] must be [java.lang.String]");
}
return null;
}
Class valueType = descriptor.getMapValueType();
if (valueType == null) {
if (descriptor.isRequired()) {
throw new FatalBeanException("No value type declared for map [" + type.getName() + "]");
}
return null;
}
DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor);
targetDesc.increaseNestingLevel();
Map matchingBeans = findAutowireCandidates(beanName, valueType, targetDesc);
if (matchingBeans.isEmpty()) {
if (descriptor.isRequired()) {
raiseNoSuchBeanDefinitionException(valueType, "map with value type " + valueType.getName(), descriptor);
}
return null;
}
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
return matchingBeans;
}
else {
Map matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (descriptor.isRequired()) {
raiseNoSuchBeanDefinitionException(type, "", descriptor);
}
return null;
}
if (matchingBeans.size() > 1) {
String primaryBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (primaryBeanName == null) {
throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(primaryBeanName);
}
return matchingBeans.get(primaryBeanName);
}
// We have exactly one match.
Map.Entry entry = matchingBeans.entrySet().iterator().next();
if (autowiredBeanNames != null) {
autowiredBeanNames.add(entry.getKey());
}
return entry.getValue();
}
}
这里包含了对String的处理,对List Collection Map等的处理,这些都不是常用注入类型,我们直接看重点:
else {
Map matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (descriptor.isRequired()) {
raiseNoSuchBeanDefinitionException(type, "", descriptor);
}
return null;
}
if (matchingBeans.size() > 1) {
String primaryBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (primaryBeanName == null) {
throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(primaryBeanName);
}
return matchingBeans.get(primaryBeanName);
}
// We have exactly one match.
Map.Entry entry = matchingBeans.entrySet().iterator().next();
if (autowiredBeanNames != null) {
autowiredBeanNames.add(entry.getKey());
}
return entry.getValue();
}
这里分为三种情况,没有找到匹类型,找到多个匹配类型,恰好有一个匹配类型,对于有多个结果,根据 @Primary和@Priority决策最佳对象。
到这里,所有的依赖注入属性以及对象都已经获得,且放在属性对象MutablePropertyValues以及局部对象里等。下面要进行的就是applyPropertyValues(beanName, mbd, bw, pvs);,将注入对象apply到目标对象上。
/**
* Apply the given property values, resolving any runtime references
* to other beans in this bean factory. Must use deep copy, so we
* don't permanently modify this property.
* @param beanName the bean name passed for better exception information
* @param mbd the merged bean definition
* @param bw the BeanWrapper wrapping the target object
* @param pvs the new property values
*/
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
if (pvs == null || pvs.isEmpty()) {
return;
}
MutablePropertyValues mpvs = null;
List original;
if (System.getSecurityManager() != null) {
if (bw instanceof BeanWrapperImpl) {
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
}
}
if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
if (mpvs.isConverted()) {
// Shortcut: use the pre-converted values as-is.
try {
bw.setPropertyValues(mpvs);
return;
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
original = mpvs.getPropertyValueList();
}
else {
original = Arrays.asList(pvs.getPropertyValues());
}
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
// Create a deep copy, resolving any references for values.
List deepCopy = new ArrayList(original.size());
boolean resolveNecessary = false;
for (PropertyValue pv : original) {
if (pv.isConverted()) {
deepCopy.add(pv);
}
else {
String propertyName = pv.getName();
Object originalValue = pv.getValue();
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
Object convertedValue = resolvedValue;
boolean convertible = bw.isWritableProperty(propertyName) &&
!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
if (convertible) {
convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
}
// Possibly store converted value in merged bean definition,
// in order to avoid re-conversion for every created bean instance.
if (resolvedValue == originalValue) {
if (convertible) {
pv.setConvertedValue(convertedValue);
}
deepCopy.add(pv);
}
else if (convertible && originalValue instanceof TypedStringValue &&
!((TypedStringValue) originalValue).isDynamic() &&
!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
pv.setConvertedValue(convertedValue);
deepCopy.add(pv);
}
else {
resolveNecessary = true;
deepCopy.add(new PropertyValue(pv, convertedValue));
}
}
}
if (mpvs != null && !resolveNecessary) {
mpvs.setConverted();
}
// Set our (possibly massaged) deep copy.
try {
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
此方法将属性设置到BeanWrapper中后,回到doCreateBean进一步调用此方法 exposedObject = initializeBean(beanName, exposedObject, mbd);
/**
* Initialize the given bean instance, applying factory callbacks
* as well as init methods and bean post processors.
* Called from {@link #createBean} for traditionally defined beans,
* and from {@link #initializeBean} for existing bean instances.
* @param beanName the bean name in the factory (for debugging purposes)
* @param bean the new bean instance we may need to initialize
* @param mbd the bean definition that the bean was created with
* (can also be {@code null}, if given an existing bean instance)
* @return the initialized bean instance (potentially wrapped)
* @see BeanNameAware
* @see BeanClassLoaderAware
* @see BeanFactoryAware
* @see #applyBeanPostProcessorsBeforeInitialization
* @see #invokeInitMethods
* @see #applyBeanPostProcessorsAfterInitialization
*/
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction() {
@Override
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
首先说下对Aware的处理,在Spring中提供一些Aware接口比如BeanFactoryAware ApplicationContextAware等,实现这些Aware接口的bean在实例化后,可以取得一些相应的资源,比如实现了BeanFactoryAware,则实例化时会注入BeanFactory实例。 invokeAwareMethods(beanName, bean);就是做了这些的处理。
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
这段代码,还是我们说过的,获取用户实例,给用户一个扩展自己的processor的机会。
在applyPropertyValues方法中,我们看到了bw.setPropertyValues(mpvs)方法的调用,其实这里并不是真正的将属性注入了,调用之后,后续的任务交给了BeeanWrapperImpl类去出去,而函数本身则跳出并返回了创建的 对象。不由的说下Spring的单一职责原则和分派处理设计的多么强大。我们看下进一步的处理,跟踪BeanWrapperImpl类,我们找到了最核心的部分,中间函数的跟踪此处不在说明了。最后到此方法:
@Override
public void setValue(final Object object, Object valueToApply) throws Exception {
final Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
this.pd.getWriteMethod());
if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers()) && !writeMethod.isAccessible()) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction() {
@Override
public Object run() {
writeMethod.setAccessible(true);
return null;
}
});
}
else {
writeMethod.setAccessible(true);
}
}
final Object value = valueToApply;
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction() {
@Override
public Object run() throws Exception {
writeMethod.invoke(object, value);
return null;
}
}, acc);
}
catch (PrivilegedActionException ex) {
throw ex.getException();
}
}
else {
writeMethod.invoke(getWrappedInstance(), value);
}
}
这里invoke了write方法,即set方法,属性值即为参数。到这里,属性才是真正的注入了。
你可能感兴趣的:(Spring源码阅读3-bean获取-下)
vite+vue+ts+element-plus从零开发管理后台框架(12)-logo和标题
vue3
编辑src/views/Main.vue,template段header-left修改如下。logo和标题全部在router-link标签下,即点击的时候会跳转到/这个路由,展开状态下显示logo和标题,折叠状态下只显示logo。VEVueElementstyle段header-left修改如下,这里要注意route-link渲染之后就是a标签。.header-left{&a{height:60p
是时候解决告警事件数据孤岛问题了
监控告警告警风暴
大家有没有发现,随着公司发展,慢慢引入了越来越多的监控、可观测性的系统,云上的、云下的,开源的、商业的,通用的、特定产品的,导致告警事件分散在非常多的地方,形成一个一个的数据孤岛。比如下面这些监控系统,你们应该不止用了一个吧:上图中有些系统你可能会困惑,比如OceanBase,明明是个数据库,为啥出现在这里。因为OceanBase自己内置有自己的监控能力,没有复用Prometheus之类的通用监控
用双色球数据集微调后的大模型
qq_29790801
人工智能 NLP
最近用Qwen/Qwen1.5-1.8B-Chat大模型来微调训练双色球2003001-2025011的数据集,实验测一下大模型出球的预测情况。使用输入期数看它的输出如:prompt="2025012"messages=[6,10,14,17,23,25,12}]有兴趣的朋友也可以下载玩玩魔塔社区下载模型地址:魔搭社区魔塔社区下载数据集地址:魔搭社区huggingface下载模型地址:https:
手把手教你将 DeepSeek 集成到 Java 的 Spring Boot 项目中
Java_young
AI java spring boot 开发语言
前面阳仔给大家介绍了如何将deepseek结合进入办公软件中,今天阳仔将详细介绍如何将DeepSeek集成到Java的SpringBoot项目中,让你的项目具备智能交互能力。一、准备工作1.注册DeepSeek账号并获取APIKey访问DeepSeek官网,点击右上角的“开放平台”,注册或登录账号。在左侧菜单中点击“APIKeys”,点击“创建APIKey”,为APIKey命名(如“test”),
避坑指南:chatgpt账号购买成品号- chatgpt 4.0 plus成品号购买手册!
openai
购买ChatGPT账号的注意事项及指南✨在当前人工智能技术快速发展的背景下,ChatGPT作为一种强大的语言模型工具️,受到了广泛关注。然而,在获取ChatGPT账号的过程中,用户需审慎考虑多项关键因素,以确保所购账号的安全、可靠及合法性✅,规避潜在风险⚠️。本文将深入探讨购买ChatGPT账号时需重点关注的几个方面,并提供相关建议。1.账号来源审查️♂️账号来源是决定其安全性和可靠性的首要因素
服装消费“变天”,行业风向几何?
xss
服装消费环境之变:现象初窥不知你是否留意到,曾经热闹非凡的商场里,一些熟悉的服装品牌门店正在悄然减少。ZARA姐妹品牌Oysho从中国市场撤退,大量门店关闭,就连天猫旗舰店也于2024年11月17日关闭,这一事件引发了不少消费者的感慨。而这并非个例,太平鸟业绩连续三年下滑,2024年营业收入68.31亿元,同比下降12.34%;归母净利润2.57亿元,同比下降39.06%,大规模关店也在同步进行。
面试__八股
big muscle
Java 面试 linux jvm
java解释执行,即时编译(编译成本地代码,效率高,内存占用多,C1,C2)编译优化技术:方法内联,复写传播,无用代码删除字节码就是虚拟机所使用的指令集类加载:加载(获取类的二进制流文件,方法区的数据结构,内存生成这个类的class对象),链接(验证,准备(类变量初始化),解析(符号引用替换为直接引用)),初始化(常量初始化)栈帧主要是局部变量区和操作数栈,方法返回地址,对象头的markword;
影视会员接口api对接过程中需要注意什么事项?
绝缘体1
pygame 大数据 pandas 网络 运维
在对接影视会员API接口的过程中,需要注意以下几个关键事项,以确保集成过程顺利且安全:1.了解API接口API功能:明确API接口的功能,如会员权益查询、影片库访问、会员价格获取等。接口文档:详细阅读API文档,了解请求参数、请求方法、请求URL、响应格式及可能的错误代码。2.对接前的准备工作注册账号:在API服务提供商的平台上注册开发者账号,并获取APIKey和Secret,这些信息将用于接口的
【从0到1构建高并发后端系统:Spring Boot + Redis + RabbitMQ实战指南】
小怪兽9699
spring boot
一、架构演进路径图图1:从单体架构到微服务集群的演进过程二、核心优化策略与落地实践1.数据库优化方案分库分表实践://ShardingSphere分片策略配置spring:shardingsphere:datasource:names:ds0,ds1rules:sharding:tables:order:actual-data-nodes:ds$->{0..1}.order_$->{0..3}ta
【从0到1构建实时聊天系统:Spring Boot + Vue3 + WebSocket全栈实战】
小怪兽9699
spring boot websocket 后端
一、项目架构技术栈清单:后端:SpringBoot3.0+WebSocket+STOMP前端:Vue3+Pinia+WebSocketClient部署:Nginx+DockerCompose二、核心功能实现1.WebSocket双向通信//后端配置类@Configuration@EnableWebSocketMessageBrokerpublicclassWebSocketConfigimplem
Linux系统之bc命令详解
门前灯
linux 运维 服务器 bc bc命令详解
bc(BasicCalculator)是一个在Unix和类Unix操作系统中提供的任意精度计算语言。它支持基本的数学运算,包括加、减、乘、除以及指数运算,并且能够处理浮点数和整数。此外,bc还支持编程特性,如变量定义、条件判断、循环结构等,使其不仅仅是一个计算器,更是一个完整的编程环境。基本语法启动bc交互模式:直接在终端中输入bc即可进入交互模式,在该模式下可以实时输入并计算表达式。bc非交互模
C#在Word表格中插入图片调整大小Debug
觀星
其他 c# msword InlineShape AddPicture 自动调整单元格大小
C#在Word表格中插入图片调整大小Debug一、C#在Word表格中插入图片并调整大小二、设置单元格大小随图片大小变化一、C#在Word表格中插入图片并调整大小C#编程中在word中和Word表格中插入图片是使用InlineShapes.AddPicture方法,方法官方微软说明如下:具体示例代码见本博客下使用C#对Word进行读写、搜索、插入图片等操作文章。在Word中的表格单元格中插入图片后
智能遥感新质生产力:ChatGPT、Python和OpenCV强强联合;空天地遥感数据分析的全流程;地面数据、无人机数据、卫星数据、多源数据等处理
小艳加油
DeepSeek ChatGPT 遥感 遥感 新质生产力 ChatGPT OpenCV 遥感数据处理
通过系统化的模块设计和丰富的实战案例,深入理解和掌握遥感数据的处理与计算。不仅涵盖了从零基础入门Python编程、OpenCV视觉处理的基础知识,还将借助ChatGPT智能支持,引导您掌握遥感影像识别和分析的进阶技术。更为重要的是,通过15个经过精心设计的真实案例,深度参与地质监测、城市规划、农业分析、生态评估等不同场景下的遥感应用实践。层层递进、结构严谨,帮助您系统性掌握从数据预处理、图像增强、
打造RAG系统:四大向量数据库Milvus、Faiss、Elasticsearch、Chroma 全面对比与选型指南
橙子小哥的代码世界
数据库 数据库 milvus faiss 人工智能 深度学习 神经网络 elasticsearch
在当今信息爆炸的时代,检索增强生成(Retrieval-AugmentedGeneration,简称RAG)系统已成为自然语言处理(NLP)领域的重要工具。RAG系统通过结合生成模型和信息检索技术,能够在大规模数据中高效地获取相关信息,生成更为精准和有针对性的内容。而在构建RAG系统时,选择合适的向量数据库是确保系统性能和可扩展性的关键一步。本文将深入对比四大主流向量数据库——Milvus、Fai
H.264---序列参数集(SPS)---宽高获取
SXM19940913sxm
H264
SequenceParamaterSet(NALUnit=7)SPS和PPS一般处于码流的起始位置,但也可能出现在码流中间,主要原因是:1、解码器需要在码流中间开始解码;2、编码器在编码的过程中改变了码流的参数(如图像分辨率等);SPS结构(H264文档7.3.2.1)/**SequenceParameterSet@see7.3.2.1SequenceparametersetRBSPsyntax*
Spring Boot整合MinIO对象存储教程
嘵奇
提升自己 spring boot 后端 java
精心整理了最新的面试资料和简历模板,有需要的可以自行获取点击前往百度网盘获取点击前往夸克网盘获取以下是一份详细的SpringBoot整合MinIO的教程,包含基础配置和常用文件操作示例:SpringBoot整合MinIO对象存储教程一、MinIO简介MinIO是一款高性能、云原生的分布式对象存储系统,兼容AmazonS3API。适用于存储图片、文档、视频等非结构化数据。二、环境准备安装MinIO服
MVVM及数据代理
真der~啊
Vue2 Vue2
MVVM及数据代理2.2.1MVVM分层思想MVVM是什么?M:Model(模型/数据):代表应用程序的数据和业务逻辑,它可以是从服务器获取的数据、本地存储的数据,或者是应用程序内部产生的数据。例如,在一个电商应用中,商品的信息(如名称、价格、库存等)就属于Model的范畴。V:View(视图):负责展示数据给用户,是用户直接交互的界面部分。比如电商应用中的商品列表页面、商品详情页面等。VM:Vi
SpringBoot+Vue前后端分离项目的搭建及简单开发(这次保证看明白~)
m0_67265464
前端 html javascript 开发语言 ecmascript
文章目录概述一、搭建SpringBoot后端1.sql脚本2.新建SpringBoot项目3.MP代码生成4.编写Controller二、搭建Vue前端1.IDEA安装Vue.js插件2.IDEA启动Vue项目3.编写Vue代码4.接收后端数据三、ElementUI使用1.简单的数据展示2.Element-ui更多…参看:https://www.bilibili.com/video/BV13741
linux 下 CUDA + Opencv 编程 之 CMakeLists.txt
maxruan
编程 图像处理 CUDA opencv linux c++ cuda
CMAKE_MINIMUM_REQUIRED(VERSION2.8)PROJECT(medianFilterGPU)#CUDApackageFIND_PACKAGE(CUDAREQUIRED)INCLUDE(FindCUDA)#CUDAincludedirectoriesINCLUDE_DIRECTORIES(/usr/local/cuda/include)#OpenCVpackageFIND_P
Win11及CUDA 12.1环境下PyTorch安装及避坑指南:深度学习开发者的福音
郁云爽
Win11及CUDA12.1环境下PyTorch安装及避坑指南:深度学习开发者的福音【下载地址】Win11及CUDA12.1环境下PyTorch安装及避坑指南本资源文件旨在为在Windows11操作系统及CUDA12.1环境下安装PyTorch的用户提供详细的安装步骤及常见问题解决方案。无论你是初学者还是有经验的开发者,这份指南都将帮助你顺利完成PyTorch的安装,并避免常见的坑项目地址:htt
必看!计算机毕设答辩高分技巧,让你脱颖而出
源码姑娘
毕业设计
必看!计算机毕设答辩高分技巧,让你脱颖而出一、答辩前的充分准备:技术与内容的“双向打磨”1.吃透项目,技术实现了然于胸计算机毕设的核心在于技术逻辑与系统设计的合理性。答辩前需反复回顾代码实现、架构设计、数据库模型等关键细节,确保能清晰阐述以下问题:技术选型依据:为何选择SpringBoot而非其他框架?所选算法的优势与局限性是什么?系统功能验证:如何通过测试用例或用户反馈验证系统可行性?若涉及机器
华为手机无线投屏到win10笔记本电脑
程裕强
华为手机 win10电脑 无线投屏
1、win10笔记本电脑设置(1)开始菜单–>设置,进入Windows设置(2)单击“系统”,进入系统设置页面(3)选择投影到此电脑2、华为手机设置(1)与笔记本电脑在同一网络下(2)手机顶端下拉,找到无线投屏(3)搜索到当前笔记本电脑(4)进入无线投屏
uniapp vue3 微信小程序 uni.chooseLocation使用
HerayChen
uni-app 微信小程序 小程序 微信小程序地理位置
申请先要去微信公众平台申请使用接口开通成功之后就可以在项目中配置使用了配置配置manifest.json"mp-weixin":{/*小程序特有相关*/"requiredPrivateInfos":["chooseLocation"],"permission":{"scope.userLocation":{"desc":"你的小程序需要获取你的位置信息,以便为你提供更精准的服务。"}}}使用uni
PyBroker:利用 Python 和机器学习助力算法交易
skywalk8163
人工智能 编程语言 量化分析 python 机器学习 算法
PyBroker:利用Python和机器学习助力算法交易你是否希望借助Python和机器学习的力量来优化你的交易策略?那么你需要了解一下PyBroker!这个Python框架专为开发算法交易策略而设计,尤其关注使用机器学习的策略。借助PyBroker,你可以轻松创建和微调交易规则,构建强大的模型,并深入了解你的策略表现。PyBroker介绍官方说明文档:利用PyBroker进行量化投资官方说明文档
10个实用IntelliJ IDEA插件
嘵奇
提升自己 intellij-idea java ide
精心整理了最新的面试资料和简历模板,有需要的可以自行获取点击前往百度网盘获取点击前往夸克网盘获取以下是为提升开发效率推荐的10个实用IntelliJIDEA插件,涵盖代码质量、效率工具及热门框架支持:一、代码质量与规范SonarLint实时代码缺陷检测,提前规避潜在Bug,支持自定义规则与SonarQube同步CheckStyle-IDEA强制代码风格统一,适配Google/阿里巴巴等主流规范,团
SpringCloud——Ribbon实现客户端负载均衡
袁雾头
SpringCloud
SpringCloud——Ribbon实现客户端负载均衡SpringCloudRibbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于NetflixRibbon实现。通过SpringCloud的封装,可以让我们轻松地将面向服务的REST模板请求自动转换成客户端负载均衡的服务调用。客户端负载均衡硬件负载均衡的设备或是软件负载均衡的软件模块都会维护一个可用的服务端清单,通过心跳检测来剔除故障
中级网络工程师面试题参考示例(5)
他不爱吃香菜
网络协议 网络面试解答 网络 网络协议 运维 面试
企业园区网络设计问题:请描述一下如何设计一个企业园区网络,包括核心层、汇聚层和接入层的功能及其关键技术。解答:核心层:负责高速数据交换,通常使用高性能的三层交换机,支持高带宽和低延迟。关键技术包括路由协议(如OSPF、EIGRP)、冗余设计(如HSRP、VRRP)以及QoS(服务质量)策略。汇聚层:连接核心层和接入层,负责聚合流量并进行策略控制。关键技术包括VLAN、STP(生成树协议)、链路聚合
简单的网络巡检脚本工具(仅供参考)
他不爱吃香菜
网络协议 网络 python 网络协议
以下是一个基于Python的网络设备自动巡检备份脚本示例,支持华为、华三(H3C)、思科、锐捷等厂商的设备。该脚本使用paramiko库进行SSH连接,并通过执行命令获取设备配置并保存到本地文件中。脚本功能:支持多厂商设备(华为、H3C、思科、锐捷)。自动登录设备并执行巡检命令。备份设备配置到本地文件。支持多设备批量操作。依赖库:paramiko:用于SSH连接。安装命令:pipinstallpa
基于USB Key的Web系统双因素认证解决方案:构建安全与便捷的登录体系
安 当 加 密
安全 网络 运维
摘要在网络安全威胁日益严峻的背景下,传统的“用户名+密码”认证方式已难以应对钓鱼攻击、密码窃取等风险。上海安当基于USBKey技术,推出了一套面向Web系统的双因素认证解决方案,通过硬件与密码学的深度融合,实现用户身份的高强度验证。本文将从技术原理、实现流程、核心优势及典型应用场景等角度,详细解析该方案的设计与实践。一、技术原理与核心组件1.USBKey的双因素认证机制USBKey作为硬件载体,结
苍穹外卖(Springboot3实现) day01
十年不明
苍穹外卖学习 spring spring boot java
黑马给的起步代码基础工程版本是springboot2.x我的电脑用的是JDK21springboot3.x所以第一天整了很长时间需要慢慢修改配置环境目录依赖版本更换springboot版本更换mybatis版本更换lombok版本更换数据库依赖更新(很重要)swagger配置问题代码补全依赖版本更换springboot版本更换父工程sky-take-out的pom文件添加spring-boot-s
SQL的各种连接查询
xieke90
UNION ALL UNION 外连接 内连接 JOIN
一、内连接
概念:内连接就是使用比较运算符根据每个表共有的列的值匹配两个表中的行。
内连接(join 或者inner join )
SQL语法:
select * fron
java编程思想--复用类
百合不是茶
java 继承 代理 组合 final类
复用类看着标题都不知道是什么,再加上java编程思想翻译的比价难懂,所以知道现在才看这本软件界的奇书
一:组合语法:就是将对象的引用放到新类中即可
代码:
package com.wj.reuse;
/**
*
* @author Administrator 组
[开源与生态系统]国产CPU的生态系统
comsci
cpu
计算机要从娃娃抓起...而孩子最喜欢玩游戏....
要让国产CPU在国内市场形成自己的生态系统和产业链,国家和企业就不能够忘记游戏这个非常关键的环节....
投入一些资金和资源,人力和政策,让游
JVM内存区域划分Eden Space、Survivor Space、Tenured Gen,Perm Gen解释
商人shang
jvm内存
jvm区域总体分两类,heap区和非heap区。heap区又分:Eden Space(伊甸园)、Survivor Space(幸存者区)、Tenured Gen(老年代-养老区)。 非heap区又分:Code Cache(代码缓存区)、Perm Gen(永久代)、Jvm Stack(java虚拟机栈)、Local Method Statck(本地方法栈)。
HotSpot虚拟机GC算法采用分代收
页面上调用 QQ
oloz
qq
<A href="tencent://message/?uin=707321921&Site=有事Q我&Menu=yes">
<img style="border:0px;" src=http://wpa.qq.com/pa?p=1:707321921:1></a>
一些问题
文强chu
问题
1.eclipse 导出 doc 出现“The Javadoc command does not exist.” javadoc command 选择 jdk/bin/javadoc.exe 2.tomcate 配置 web 项目 .....
SQL:3.mysql * 必须得放前面 否则 select&nbs
生活没有安全感
小桔子
生活 孤独 安全感
圈子好小,身边朋友没几个,交心的更是少之又少。在深圳,除了男朋友,没几个亲密的人。不知不觉男朋友成了唯一的依靠,毫不夸张的说,业余生活的全部。现在感情好,也很幸福的。但是说不准难免人心会变嘛,不发生什么大家都乐融融,发生什么很难处理。我想说如果不幸被分手(无论原因如何),生活难免变化很大,在深圳,我没交心的朋友。明
php 基础语法
aichenglong
php 基本语法
1 .1 php变量必须以$开头
<?php
$a=” b”;
echo
?>
1 .2 php基本数据库类型 Integer float/double Boolean string
1 .3 复合数据类型 数组array和对象 object
1 .4 特殊数据类型 null 资源类型(resource) $co
mybatis tools 配置详解
AILIKES
mybatis
MyBatis Generator中文文档
MyBatis Generator中文文档地址:
http://generator.sturgeon.mopaas.com/
该中文文档由于尽可能和原文内容一致,所以有些地方如果不熟悉,看中文版的文档的也会有一定的障碍,所以本章根据该中文文档以及实际应用,使用通俗的语言来讲解详细的配置。
本文使用Markdown进行编辑,但是博客显示效
继承与多态的探讨
百合不是茶
JAVA面向对象 继承 对象
继承 extends 多态
继承是面向对象最经常使用的特征之一:继承语法是通过继承发、基类的域和方法 //继承就是从现有的类中生成一个新的类,这个新类拥有现有类的所有extends是使用继承的关键字:
在A类中定义属性和方法;
class A{
//定义属性
int age;
//定义方法
public void go
JS的undefined与null的实例
bijian1013
JavaScript JavaScript
<form name="theform" id="theform">
</form>
<script language="javascript">
var a
alert(typeof(b)); //这里提示undefined
if(theform.datas
TDD实践(一)
bijian1013
java 敏捷 TDD
一.TDD概述
TDD:测试驱动开发,它的基本思想就是在开发功能代码之前,先编写测试代码。也就是说在明确要开发某个功能后,首先思考如何对这个功能进行测试,并完成测试代码的编写,然后编写相关的代码满足这些测试用例。然后循环进行添加其他功能,直到完全部功能的开发。
[Maven学习笔记十]Maven Profile与资源文件过滤器
bit1129
maven
什么是Maven Profile
Maven Profile的含义是针对编译打包环境和编译打包目的配置定制,可以在不同的环境上选择相应的配置,例如DB信息,可以根据是为开发环境编译打包,还是为生产环境编译打包,动态的选择正确的DB配置信息
Profile的激活机制
1.Profile可以手工激活,比如在Intellij Idea的Maven Project视图中可以选择一个P
【Hive八】Hive用户自定义生成表函数(UDTF)
bit1129
hive
1. 什么是UDTF
UDTF,是User Defined Table-Generating Functions,一眼看上去,貌似是用户自定义生成表函数,这个生成表不应该理解为生成了一个HQL Table, 貌似更应该理解为生成了类似关系表的二维行数据集
2. 如何实现UDTF
继承org.apache.hadoop.hive.ql.udf.generic
tfs restful api 加auth 2.0认计
ronin47
目前思考如何给tfs的ngx-tfs api增加安全性。有如下两点:
一是基于客户端的ip设置。这个比较容易实现。
二是基于OAuth2.0认证,这个需要lua,实现起来相对于一来说,有些难度。
现在重点介绍第二种方法实现思路。
前言:我们使用Nginx的Lua中间件建立了OAuth2认证和授权层。如果你也有此打算,阅读下面的文档,实现自动化并获得收益。SeatGe
jdk环境变量配置
byalias
java jdk
进行java开发,首先要安装jdk,安装了jdk后还要进行环境变量配置:
1、下载jdk(http://java.sun.com/javase/downloads/index.jsp),我下载的版本是:jdk-7u79-windows-x64.exe
2、安装jdk-7u79-windows-x64.exe
3、配置环境变量:右击"计算机"-->&quo
《代码大全》表驱动法-Table Driven Approach-2
bylijinnan
java
package com.ljn.base;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.uti
SQL 数值四舍五入 小数点后保留2位
chicony
四舍五入
1.round() 函数是四舍五入用,第一个参数是我们要被操作的数据,第二个参数是设置我们四舍五入之后小数点后显示几位。
2.numeric 函数的2个参数,第一个表示数据长度,第二个参数表示小数点后位数。
例如:
select cast(round(12.5,2) as numeric(5,2))
c++运算符重载
CrazyMizzz
C++
一、加+,减-,乘*,除/ 的运算符重载
Rational operator*(const Rational &x) const{
return Rational(x.a * this->a);
}
在这里只写乘法的,加减除的写法类似
二、<<输出,>>输入的运算符重载
&nb
hive DDL语法汇总
daizj
hive 修改列 DDL 修改表
hive DDL语法汇总
1、对表重命名
hive> ALTER TABLE table_name RENAME TO new_table_name;
2、修改表备注
hive> ALTER TABLE table_name SET TBLPROPERTIES ('comment' = new_comm
jbox使用说明
dcj3sjt126com
Web
参考网址:http://www.kudystudio.com/jbox/jbox-demo.html jBox v2.3 beta [
点击下载]
技术交流QQGroup:172543951 100521167
[2011-11-11] jBox v2.3 正式版
- [调整&修复] IE6下有iframe或页面有active、applet控件
UISegmentedControl 开发笔记
dcj3sjt126com
// typedef NS_ENUM(NSInteger, UISegmentedControlStyle) {
// UISegmentedControlStylePlain, // large plain
&
Slick生成表映射文件
ekian
scala
Scala添加SLICK进行数据库操作,需在sbt文件上添加slick-codegen包
"com.typesafe.slick" %% "slick-codegen" % slickVersion
因为我是连接SQL Server数据库,还需添加slick-extensions,jtds包
"com.typesa
ES-TEST
gengzg
test
package com.MarkNum;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation
为何外键不再推荐使用
hugh.wang
mysql DB
表的关联,是一种逻辑关系,并不需要进行物理上的“硬关联”,而且你所期望的关联,其实只是其数据上存在一定的联系而已,而这种联系实际上是在设计之初就定义好的固有逻辑。
在业务代码中实现的时候,只要按照设计之初的这种固有关联逻辑来处理数据即可,并不需要在数据库层面进行“硬关联”,因为在数据库层面通过使用外键的方式进行“硬关联”,会带来很多额外的资源消耗来进行一致性和完整性校验,即使很多时候我们并不
领域驱动设计
julyflame
VO DAO 设计模式 DTO po
概念:
VO(View Object):视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来。
DTO(Data Transfer Object):数据传输对象,这个概念来源于J2EE的设计模式,原来的目的是为了EJB的分布式应用提供粗粒度的数据实体,以减少分布式调用的次数,从而提高分布式调用的性能和降低网络负载,但在这里,我泛指用于展示层与服务层之间的数据传输对
单例设计模式
hm4123660
java Singleton 单例设计模式 懒汉式 饿汉式
单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
&nb
logback
zhb8015
log logback
一、logback的介绍
Logback是由log4j创始人设计的又一个开源日志组件。logback当前分成三个模块:logback-core,logback- classic和logback-access。logback-core是其它两个模块的基础模块。logback-classic是log4j的一个 改良版本。此外logback-class
整合Kafka到Spark Streaming——代码示例和挑战
Stark_Summer
spark storm zookeeper PARALLELISM processing
作者Michael G. Noll是瑞士的一位工程师和研究员,效力于Verisign,是Verisign实验室的大规模数据分析基础设施(基础Hadoop)的技术主管。本文,Michael详细的演示了如何将Kafka整合到Spark Streaming中。 期间, Michael还提到了将Kafka整合到 Spark Streaming中的一些现状,非常值得阅读,虽然有一些信息在Spark 1.2版
spring-master-slave-commondao
王新春
DAO spring dataSource slave master
互联网的web项目,都有个特点:请求的并发量高,其中请求最耗时的db操作,又是系统优化的重中之重。
为此,往往搭建 db的 一主多从库的 数据库架构。作为web的DAO层,要保证针对主库进行写操作,对多个从库进行读操作。当然在一些请求中,为了避免主从复制的延迟导致的数据不一致性,部分的读操作也要到主库上。(这种需求一般通过业务垂直分开,比如下单业务的代码所部署的机器,读去应该也要从主库读取数