SpringAOP -- JDK代理解析

系列文章目录

切点匹配解析
Advisor与@Aspect解析
getPointcut解析
Advisor解析



1. ProxyFactory类创建代理

SpringAOP中通过wrapIfNecessary()方法为目标对象创建代理(createProxy方法)

参数:
bean.getClass(): 目标bean类对象
beenName: bean名称
specificInterceptors: 匹配到的切面集合
new SingletonTargetSource(bean): 为目标bean创建单例工厂
@Override
public Object wrapIfNecessary(Object bean, String beanName, Object cacheKey){
    // 找到和当前bean匹配的advisor
    Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
    // 创建代理 specificInterceptors:特殊Interceptors -> 可匹配的切面集合  SingletonTargetSource:创建当前bean的单例bean工厂
    Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
    return proxy;
}

createProxy()类解析
当前类扩展了ProxyProcessorSupport类,该类同时又扩展了ProxyConfig类
在这里插入图片描述
createProxy()中主要创建ProxyFactory()代理工厂
在这里插入图片描述
可以看见ProxyFactory与当前类对象AbstractAutoProxyCreator均继承了ProxyConfig类,createProxy()主要创建了ProxyFactory()代理工厂,并为其进行初始化以便于后续代理生成

protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) {
    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory)this.beanFactory, beanName, beanClass);
    }
	// 实例化代理工厂
    ProxyFactory proxyFactory = new ProxyFactory();
    // 传入this给代理工厂赋值 
    // 当前类实例 与 代理工厂均继承了ProxyConfig类 即可以对公共成员进行赋值
    proxyFactory.copyFrom(this);
    // 默认false ProxyTargetClass 是否强制CGLIB生成代理
    if (proxyFactory.isProxyTargetClass()) {
        if (Proxy.isProxyClass(beanClass) || ClassUtils.isLambdaClass(beanClass)) {
            Class[] var6 = beanClass.getInterfaces();
            int var7 = var6.length;

            for(int var8 = 0; var8 < var7; ++var8) {
                Class<?> ifc = var6[var8];
                proxyFactory.addInterface(ifc);
            }
        }
    } else if (this.shouldProxyTargetClass(beanClass, beanName)) {
        proxyFactory.setProxyTargetClass(true);
    } else {
    	// 验证当前bean对象实现接口是否为 可代理接口; 若是,则将其接口类添加到工厂接口成员中
    	// 若否则设置 proxyFactory.setProxyTargetClass(true) 强制CGLIB代理
        this.evaluateProxyInterfaces(beanClass, proxyFactory);
    }
	// 根据specificInterceptors(切面集合) 构造advisors集合
    Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors);
    // 添加切面集合
    proxyFactory.addAdvisors(advisors);
    // 添加单例bean工厂
    proxyFactory.setTargetSource(targetSource);
    this.customizeProxyFactory(proxyFactory);
    proxyFactory.setFrozen(this.freezeProxy);
    if (this.advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }
	// 获取类加载器
    ClassLoader classLoader = this.getProxyClassLoader();
    if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
        classLoader = ((SmartClassLoader)classLoader).getOriginalClassLoader();
    }
	// 创建代理
    return proxyFactory.getProxy(classLoader);
}

getProxy()方法中实际在返回proxyFactory中的createAopProxy().getProxy(),而createAopProxy()则返回了getAopProxyFactory().createAopProxy(this), 最后getAopProxyFactory()则实际获取了aopProxyFactory对象,其实际为new DefaultAopProxyFactory()实例化对象 作为父类ProxyCreatorSupport的成员.

// 创建代理
public Object getProxy(@Nullable ClassLoader classLoader) {
    return this.createAopProxy().getProxy(classLoader);
}

// createAopProxy是beanFactory父类ProxyCreatorSupport类中的方法
protected final synchronized AopProxy createAopProxy() {
    if (!this.active) {
        this.activate();
    }
	// 传入proxyFactory对象
    return this.getAopProxyFactory().createAopProxy(this);
}
// ProxyCreatorSupport中的方法
public AopProxyFactory getAopProxyFactory() {
    return this.aopProxyFactory;
}
// ProxyCreatorSupport类构造方法
// 因为ProxyFactroy实例化时调用空参构造器-> 调用父类构造器空参 ->调用ProxyCreatorSupport()方法
public ProxyCreatorSupport() {
    this.aopProxyFactory = new DefaultAopProxyFactory();
}

将上述过程简化出来则是这个样子:

// 简化结果
public Object getProxy(@Nullable ClassLoader classLoader) {
    return new DefaultAopProxyFactory().createAopProxy(this).getProxy(classLoader);
}

主要是通过DefaultAopProxyFactory()类进行代理创建,createAopProxy()主要是设定当前代理类是进行JDK代理还是进行CGLIB代理两种方式,并创建对应的代理对象.

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
    private static final long serialVersionUID = 7930414337282325166L;

    public DefaultAopProxyFactory() {
    }
	// createAopProxy()主要设置当前是进行jdk代理还是cjlib代理
	// AdvisedSupport config -> proxyFactory类实例
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        // proxyFactory.isOptimize() 是否优化生成代理策略 默认false
        // ProxyTargetClass 是否强制CGLIB生成代理
        // hasNoUserSuppliedProxyInterfaces(proxyFactory): 目标类是否实现接口,若实现是否非SpringProxy类型
        // 未优化 未强制CGLIB 实现接口且非SpringProxy类型 -> JDK动态代理
        if (NativeDetector.inNativeImage() || !config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
            return new JdkDynamicAopProxy(config);
        } else {
        	// beanFactory.getTargetClass() -> this.targetSource.getTargetClass()
        	// targetSource: 单例目标bean工厂 初始化beanfactory设置 
        	// 获取单例目标bean的类对象
            Class<?> targetClass = config.getTargetClass();
            if (targetClass == null) {
                throw new AopConfigException("TargetSource cannot determine target class: Either an interface or a target is required for proxy creation.");
            } else {
            	// 若单例目标bean的类对象不是接口 且bean类非代理创建类 且bean类对象非lambda表达式类 则使用CGLIB代理 
            	// 否则 JDK代理
                return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) && !ClassUtils.isLambdaClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
            }
        }
    }
}

// 简化结果
public Object getProxy(@Nullable ClassLoader classLoader) {
	// 以JDK为例
    return new JdkDynamicAopProxy(config)).getProxy(classLoader);
}

2. JDK创建代理

2.1 JDK代理构造函数

JDK构造函数主要进行代理对象的接口信息获取

// config -> beanFactory对象
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
    Assert.notNull(config, "AdvisedSupport must not be null");
    if (config.getAdvisorCount() == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
        throw new AopConfigException("No advisors and no TargetSource specified");
    } else {
    	// advised为beanFactory对象
        this.advised = config;
        // 获取代理对象的完整接口列表 -> JDK根据接口实现代理
        this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);  
        // 标记接口下所有方法中的equals方法与hashcode方法
        this.findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces);
    }
}

2.2 获取完整代理接口completeProxiedInterfaces()

static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) {
	// 获取proxyfactory中的可代理接口 初始化proxyfactory时添加
    Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces();
    if (specifiedInterfaces.length == 0) {
        Class<?> targetClass = advised.getTargetClass();
        if (targetClass != null) {
            if (targetClass.isInterface()) {
                advised.setInterfaces(new Class[]{targetClass});
            } else if (Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
                advised.setInterfaces(targetClass.getInterfaces());
            }

            specifiedInterfaces = advised.getProxiedInterfaces();
        }
    }
	// 创建接口列表 长度为 已记录可代理接口数 + 3
    List<Class<?>> proxiedInterfaces = new ArrayList(specifiedInterfaces.length + 3);
    Class[] var4 = specifiedInterfaces;
    int var5 = specifiedInterfaces.length;

    for(int var6 = 0; var6 < var5; ++var6) {
        Class<?> ifc = var4[var6];
        if (isSealedMethod == null || Boolean.FALSE.equals(ReflectionUtils.invokeMethod(isSealedMethod, ifc))) {
            proxiedInterfaces.add(ifc);
        }
    }
	// 检查当前代理对象是否实现了SpringProxy.class接口 若实现了则是该对象是AOP代理实现对象
    if (!advised.isInterfaceProxied(SpringProxy.class)) {
    	// 若未实现 添加SpringProxy.class到接口列表中
        proxiedInterfaces.add(SpringProxy.class);
    }
    if (!advised.isOpaque() && !advised.isInterfaceProxied(Advised.class)) {
    	// 当前代理工厂非透明 且未实现Advised.class接口
        proxiedInterfaces.add(Advised.class);
    }
	// decoratingProxy 默认true
    if (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class)) {
    	// 若未实现装饰代理接口DecoratingProxy.class 则添加到代理列表中
        proxiedInterfaces.add(DecoratingProxy.class);
    }

    return ClassUtils.toClassArray(proxiedInterfaces);
}

实例化对象后通过getProxy()方法创建代理->传入类加载器、实现代理接口、已经hanlder方法(this JDK对象自身 -> 即该对象实现了InvocationHandler接口且拥有invoke方法)

public Object getProxy(@Nullable ClassLoader classLoader) {
    if (logger.isTraceEnabled()) {
        logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
    }

    return Proxy.newProxyInstance(this.determineClassLoader(classLoader), this.proxiedInterfaces, this);
}

2.3 JDK中的invoke()

由于JdkDynamicAopProxy类实现了InvocationHandler接口,其重写invoke()方法可以实现增强操作

@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    Object oldProxy = null;
    boolean setProxyContext = false;
    // this.advised : AdvisedSupport对象 --> proxyFactory对象
    // AdvisedSupport.targetSource 当前bean的单例bean工厂
    TargetSource targetSource = this.advised.targetSource;
    Object target = null;

    Object var12;
    try {
        if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
            Boolean var18 = this.equals(args[0]);
            return var18;
        }

        if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
            Integer var17 = this.hashCode();
            return var17;
        }

        if (method.getDeclaringClass() == DecoratingProxy.class) {
            Class var16 = AopProxyUtils.ultimateTargetClass(this.advised);
            return var16;
        }

        Object retVal;
        if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) {
            retVal = AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
            return retVal;
        }

        if (this.advised.exposeProxy) {
            oldProxy = AopContext.setCurrentProxy(proxy);
            setProxyContext = true;
        }
        // 从单例bean工厂中获取bean对象
        target = targetSource.getTarget();
        // 获取bean类对象
        Class<?> targetClass = target != null ? target.getClass() : null;
        // 获取拦截器链 (目标方法 当前bean类对象)
        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
        if (chain.isEmpty()) {
            Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
            retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
        } else { // 链非空
        	// 实例化ReflectiveMethodInvocation对象() 封装反射
            MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
            // 执行调用链及原始方法 返回值retVal
            retVal = invocation.proceed();
        }
		// 获取返回值类型
        Class<?> returnType = method.getReturnType();
        
        if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
            retVal = proxy;
        } else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
            throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);
        }

        var12 = retVal;
    } finally {
        if (target != null && !targetSource.isStatic()) {
            targetSource.releaseTarget(target);
        }

        if (setProxyContext) {
            AopContext.setCurrentProxy(oldProxy);
        }

    }

    return var12;
}

2.3.1 获取拦截器链getInterceptorsAndDynamicInterceptionAdvice()

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
    MethodCacheKey cacheKey = new MethodCacheKey(method);
    List<Object> cached = (List)this.methodCache.get(cacheKey);
    if (cached == null) {
    	// 获取拦截器链 (传入 AdviceSupport对象 目标方法 bean类对象)
        cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);
        this.methodCache.put(cacheKey, cached);
    }

    return cached;
}

拦截器链实际通过getInterceptorsAndDynamicInterceptionAdvice()方法进行获取,
遍历切面集合,其中每个切面的匹配器 匹配 当前执行方法 若成功则加入将切面封装为MethodInterceptor对象并加入拦截链中

// Advised config:AdvisedSupport实例 实际就是ProxyFactory实例
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, @Nullable Class<?> targetClass) {
// 实例化DefaultAdvisorAdapterRegistry()对象registry,类型为AdvisorAdapterRegistry(多态) 默认切面适配器登记
 AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
 // AdvisedSupport父类方法getAdvisors() 获取advisors切面集合 
 // 创建ProxyFactory对象时就进行了切面赋值 proxyFactory.addAdvisors(advisors);
 Advisor[] advisors = config.getAdvisors();
 // 创建拦截器链
 List<Object> interceptorList = new ArrayList(advisors.length);
 Class<?> actualClass = targetClass != null ? targetClass : method.getDeclaringClass();
 // 设置拦截参数
 Boolean hasIntroductions = null;
 Advisor[] var9 = advisors;
 int var10 = advisors.length;
 // 遍历切面集合
 for(int var11 = 0; var11 < var10; ++var11) {
        Advisor advisor = var9[var11];
        // 非参数拦截
        if (advisor instanceof PointcutAdvisor) {
            PointcutAdvisor pointcutAdvisor = (PointcutAdvisor)advisor;
            // isPreFiltered() 为false 后者 验证 当前切面类是否能匹配bean类
            if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
                // 获取当前通知的方法匹配器
                MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                boolean match;
                // 是否涉及运行时参数匹配
                if (mm instanceof IntroductionAwareMethodMatcher) {
                    if (hasIntroductions == null) {
                        hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
                    }
                    // 匹配当前切面与当前method方法
                    match = ((IntroductionAwareMethodMatcher)mm).matches(method, actualClass, hasIntroductions);
                } else {
                	// 匹配当前切面与当前method方法
                    match = mm.matches(method, actualClass);
                }
				// 匹配成功 可以拦截
                if (match) {
                	// 创建拦截器 通过registry实例调用getInterceptors方法创建
                    MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                    // 是否为运行时参数拦截
                    if (mm.isRuntime()) {
                        MethodInterceptor[] var17 = interceptors;
                        int var18 = interceptors.length;
						// 运行时拦截器会存在多个需要分布加入拦截链表
                        for(int var19 = 0; var19 < var18; ++var19) {
                            MethodInterceptor interceptor = var17[var19];
                            interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                        }
                    } else {
                    // 普通拦截器 直接加入拦截链表
                    interceptorList.addAll(Arrays.asList(interceptors));
                    }
                }
            }
        } else if (advisor instanceof IntroductionAdvisor) {
            IntroductionAdvisor ia = (IntroductionAdvisor)advisor;
            if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
                Interceptor[] interceptors = registry.getInterceptors(advisor);
                interceptorList.addAll(Arrays.asList(interceptors));
            }
        } else {
            Interceptor[] interceptors = registry.getInterceptors(advisor);
            interceptorList.addAll(Arrays.asList(interceptors));
        }
    }

    return interceptorList;
}

2.3.2 封装切面对象 – MethodInterceptor接口类

//DefaultAdvisorAdapterRegistry类中的getInterceptors方法
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
	// 创建拦截链
    List<MethodInterceptor> interceptors = new ArrayList(3);
    // 获得切面的通知
    Advice advice = advisor.getAdvice();
    // 若通知为MethodInterceptor类型 直接添加
    if (advice instanceof MethodInterceptor) {
        interceptors.add((MethodInterceptor)advice);
    }
    // 否则需要通过适配器封装再加入拦截链中
	// 适配器列表封装了三种adapter 
	// adapters = [MethodBeforeAdviceAdapter, AfterReturningAdviceAdapter, ThrowsAdviceAdapter]
	// 实例化DefaultAdvisorAdapterRegistry类会自动填充adapters数组内容(3种适配器)
    Iterator var4 = this.adapters.iterator();
	// 遍历适配器
    while(var4.hasNext()) {
        AdvisorAdapter adapter = (AdvisorAdapter)var4.next();
        // 若当前适配器能配对当前advice通知
        if (adapter.supportsAdvice(advice)) {
        	// 通过适配器的getInterceptor方法创建匹配advice的拦截器对象
            interceptors.add(adapter.getInterceptor(advisor));
        }
    }
	// 若均不适配则抛出异常
    if (interceptors.isEmpty()) {
        throw new UnknownAdviceTypeException(advisor.getAdvice());
    } else {
    	// 返回当前拦截链
        return (MethodInterceptor[])interceptors.toArray(new MethodInterceptor[0]);
    }
}

适配器 内部封装出MethodInterceptor的特殊子类 重写了invoke方法便于后期调用拦截链方法

class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
    MethodBeforeAdviceAdapter() {
    }

    public boolean supportsAdvice(Advice advice) {
        return advice instanceof MethodBeforeAdvice;
    }
	// 根据传入的切面对象 将其封装为对应的拦截器类型(内部实现了invoke方法 便于拦截链调用)
    public MethodInterceptor getInterceptor(Advisor advisor) {
        MethodBeforeAdvice advice = (MethodBeforeAdvice)advisor.getAdvice();
        return new MethodBeforeAdviceInterceptor(advice);
    }
}

2.3.3 调用拦截器链

实例化ReflectiveMethodInvocation 反射拦截器对象并调用内部的proceed()方法执行拦截器

public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {
    protected final Object proxy;
    @Nullable
    protected final Object target;
    protected final Method method;
    protected Object[] arguments;
    @Nullable
    private final Class<?> targetClass;
    @Nullable
    private Map<String, Object> userAttributes;
    protected final List<?> interceptorsAndDynamicMethodMatchers;
    private int currentInterceptorIndex = -1;
	
	// 实例化(代理对象 单例bean对象 目标方法 参数 bean类对象 拦截器链)
    protected ReflectiveMethodInvocation(Object proxy, @Nullable Object target, Method method, @Nullable Object[] arguments, @Nullable Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {
        this.proxy = proxy;
        this.target = target;
        this.targetClass = targetClass;
        this.method = BridgeMethodResolver.findBridgedMethod(method);
        this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);
        this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
    }
    
	@Nullable
    public Object proceed() throws Throwable {
    	// currentInterceptorIndex当前拦截器下标 初始值为-1;
    	// 若下标到最后一位 调用invokeJoinpoint()方法 --> 反射执行bean目标方法
	    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
	        return this.invokeJoinpoint();
	    } else { // 未到链底
	    	// 获取下一位拦截器(下标初始-1 每次获取下一个位置的拦截器)
	        Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
	        // 是否属于带参数的类型匹配
	        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
	            InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
	            Class<?> targetClass = this.targetClass != null ? this.targetClass : this.method.getDeclaringClass();
	            // 1.验证当前参数是否满足要求 满足要求-> 带参数调用 不满足非参调用 proceed()方法
	            return dm.methodMatcher.matches(this.method, targetClass, this.arguments) ? dm.interceptor.invoke(this) : this.proceed();
	        } else { //非参数类型匹配
	        	// 调用MethodInterceptor的invoke方法 并将当前ReflectiveMethodInvocation对象传入
	            return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
	        }
	    }
	}
}

// invoke方法 MethodInterceptor类中方法
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
	// MethodInvocation mi 上述传入this -> ReflectiveMethodInvocation对象 
    try {
    	// 调用ReflectiveMethodInvocation对象的proceeed方法 -> 获得下一层拦截链 直到最后一层执行原始方法 (外部调用递归)
        return mi.proceed();
    } catch (Throwable var4) {
        Method handlerMethod = this.getExceptionHandler(var4);
        if (handlerMethod != null) {
            this.invokeHandlerMethod(mi, var4, handlerMethod);
        }
        throw var4;
    }
}

总结

本文简单讲述了springAOP中代理生成(JDK)的实现过程,并对部分源码进行了解析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值