现在,我们将对代理对象的生成过程进行分析。

springAOP源码分析(一)的例子中,将会生成哪些对象呢?

可以看到将会生成六个对象,对应的beanName分别是:

userDao:目标对象

logger:定义的切面

InternalAutoProxyCreator:用来生成代理对象的后置处理器,它实现了BeanPostProcessor,类型是AspectJAwareAdvisorAutoProxyCreator

AspectJPointcutAdvisor#0:定义的通知

AspectJPointcutAdvisor#1:定义的通知

updateUserMethod:切入点表达式

这里我们只要搞明白AspectJAwareAdvisorAutoProxyCreator和userDao这两个对象的生成过程,那么关于代理对象是如何生成的,也就清楚了。

一.AspectJAwareAdvisorAutoProxyCreator的实例化

AspectJAwareAdvisorAutoProxyCreator是一个后置处理器,它的作用是在bean对象实例化的前后可以进行一些操作。在这里,准确的说是在它的postProcessAfterInitialization方法中完成了对userDao目标对象生成了代理对象,这个方法是代理对象生成的地方,稍后再分析这个方法。现在需要思考的是对于AspectJAwareAdvisorAutoProxyCreator这个对象是什么时候生成的呢?其实它在registerBeanPostProcessors注册后置处理器的时候实例化的。进入refesh方法

public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh(); // Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory); try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation.
          //进入这个方法 
registerBeanPostProcessors(beanFactory); // Initialize message source for this context.
initMessageSource(); // Initialize event multicaster for this context.
initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses.
onRefresh(); // Check for listener beans and register them.
registerListeners(); // Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event.
finishRefresh();
} catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
} // Destroy already created singletons to avoid dangling resources.
destroyBeans(); // Reset 'active' flag.
cancelRefresh(ex); // Propagate exception to caller.
throw ex;
} finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}

进入registerBeanPostProcessors方法,然后可以追踪到以下方法

    public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
     
//获取所有的后置处理器 
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false); // Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

//对这些后置处理器进行分类存储
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
List<String> orderedPostProcessorNames = new ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}

//以下这些就是针对不同类型的后置处理器分别进行注册实例化
// First, register the BeanPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors); // Next, register the BeanPostProcessors that implement Ordered.
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
for (String ppName : orderedPostProcessorNames) {
//AspectJAwareAdvisorAutoProxyCreator的实例化就是在这里进行的
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors); // Now, register all regular BeanPostProcessors.
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors); // Finally, re-register all internal BeanPostProcessors.
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors); // Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

现在AspectJAwareAdvisorAutoProxyCreator对象已生成,那么对于其它bean实例化的时候它就可以起到后置处理器应有的作用了。

二.userDao的实例化过程

目标对象userDao的实例化过程,也包含了代理对象的生成过程,通过源码来一步步分析。

进入AbstractAutowireCapableBeanFactory类的initializeBean方法

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
} Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//对该bean调用所有后置处理器的postProcessBeforeInitialization方法
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;
}

进入applyBeanPostProcessorsAfterInitialization方法

    @Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException { Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
//获取所有的后置处理器对该bean进行操作 然后进入AbstractAutoProxyCreator的
//postProcessAfterInitialization方法中
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
进入AbstractAutoProxyCreator类的postProcessAfterInitialization方法中
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
//进入这个方法
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}

进入wrapIfNecessary方法

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
} // Create proxy if we have advice.
     // 为目标bean查找匹配的通知器
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//如果通知器的数组specificInterceptors不为空,那么生成代理对象
            Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
//把生成的代理对象放到容器中,此时beanName对应的对象不再是目标对象,而是代理对象。
return proxy;
} this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}

接下来我们去分析两个方法:为目标bean查询匹配的通知器getAdvicesAndAdvisorsForBean和代理对象的生成方法createProxy

1.查询匹配的通知器,进入getAdvicesAndAdvisorsForBean方法

protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
//进入该方法
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}

进入getAdvicesAndAdvisorsForBean方法

    protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//查找所有的通知器
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//然后筛选匹配出可应用在beanClass上的通知器
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}

2.代理对象的生成过程,有JDK动态代理和cglib两种生成方式,默认是JDK动态代理

进入createProxy方法,这个方法是代理对象生成的地方

/**
* Create an AOP proxy for the given bean.
* @param beanClass the class of the bean
* @param beanName the name of the bean
* @param specificInterceptors the set of interceptors that is
* specific to this bean (may be empty, but not null)
* @param targetSource the TargetSource for the proxy,
* already pre-configured to access the bean
* @return the AOP proxy for the bean
* @see #buildAdvisors
*/
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
} ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this); if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 获取所有的通知器,并给ProxyFactory配置通知器,目标对象
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors); // 当调用目标方法时,这些配置好的通知器就会起作用
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 此处生成代理对象,进入ProxyFactory的getProxy方法
return proxyFactory.getProxy(getProxyClassLoader());
}

进入getProxy方法,由于ProxyFactory继承ProxyCreatorSupport类,所以进入该方法后可知,真正的实现在ProxyCreatorSupport类中,调用的方法是ProxyCreatorSupport类中的方法,而ProxyFactory只是做了一层封装。

    /**
* Create a new proxy according to the settings in this factory.
* <p>Can be called repeatedly. Effect will vary if we've added
* or removed interfaces. Can add and remove interceptors.
* <p>Uses the given class loader (if necessary for proxy creation).
* @param classLoader the class loader to create the proxy with
* (or {@code null} for the low-level proxy facility's default)
* @return the proxy object
*/
public Object getProxy(ClassLoader classLoader) {
// 下面的createAopProxy()方法是ProxyCreatorSupport类中的方法
return createAopProxy().getProxy(classLoader);
}

好了,接下来是重点部分 :

createAopProxy()方法返回的是AopProxy接口类型,它有两个实现类分别是CglibAopProxy(通过cglib方式生成代理对象)和JdkDynamicAopProxy(通过JDK动态代理方式生成对象),AopProxy的作用是用于生成代理对象的,稍后将会分析这两种不同的实现方式。

那么,CglibAopProxy或者JdkDynamicAopProxy又是如何生成的呢?进入createAopProxy方法,该方法就是获取AopProxy的地方,由方法可知,这里使用了AopProxyFactory来创建AopProxy,而AopProxyFactory使用的是DefaultAopProxyFactory类。

    /**
* Subclasses should call this to get a new AOP proxy. They should <b>not</b>
* create an AOP proxy with {@code this} as an argument.
*/
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}

进入DefaultAopProxyFactory类的createAopProxy方法:

    @Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
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.");
}
// 如果targetClass是接口类,那么使用JDK来生成代理对象,返回JdkDynamicAopProxy类型的对象
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 否则,返回ObjenesisCglibAopProxy类型的对象,它是使用cglib的方式生成代理对象的
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}

到这里,我们已经清楚AopProxy是如何生成的了,那么接下来我们介绍CglibAopProxy和JdkDynamicAopProxy又是如何生成代理对象的?

JDK动态代理的方式生成代理对象,进入JdkDynamicAopProxy的getProxy方法

    @Override
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
// 取得代理对象的所有代理接口
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// 使用JDK的Proxy类来生成代理对象
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

cglib的方式生成代理对象,进入CglibAopProxy类的getProxy方法:

@Override
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
} try {
//获取目标对象
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy"); Class<?> proxySuperClass = rootClass;
if (ClassUtils.isCglibProxyClass(rootClass)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
} // Validate the class, writing log messages as necessary.
validateClassIfNecessary(proxySuperClass, classLoader);

// 创建并配置Enhancer,它是cglib主要的操作类,用于代理对象的生成
// Configure CGLIB Enhancer...
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
// 配置enhancer对象,比如 代理接口,父类,回调方法等
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader)); Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// 通过enhancer来生成代理对象
// Generate the proxy class and create a proxy instance.
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Throwable ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}

好了,现在代理对象已经生成,并且已经设置好了拦截器(通知),当代理对象调用目标方法时,就会触发这些拦截器,在下一篇文章中我们就介绍,当调用目标方法时,拦截器(通知)是如何起作用的,整个过程是怎样的。

《springAOP源码分析一》

《springAOP源码分析三》

spring AOP源码分析(二)的更多相关文章

  1. 5.2 Spring5源码--Spring AOP源码分析二

    目标: 1. 什么是AOP, 什么是AspectJ 2. 什么是Spring AOP 3. Spring AOP注解版实现原理 4. Spring AOP切面原理解析 一. 认识AOP及其使用 详见博 ...

  2. 5.2 spring5源码--spring AOP源码分析二--切面的配置方式

    目标: 1. 什么是AOP, 什么是AspectJ 2. 什么是Spring AOP 3. Spring AOP注解版实现原理 4. Spring AOP切面原理解析 一. 认识AOP及其使用 详见博 ...

  3. spring AOP源码分析(三)

    在上一篇文章 spring AOP源码分析(二)中,我们已经知道如何生成一个代理对象了,那么当代理对象调用代理方法时,增强行为也就是拦截器是如何发挥作用的呢?接下来我们将介绍JDK动态代理和cglib ...

  4. Spring AOP源码分析(三):基于JDK动态代理和CGLIB创建代理对象的实现原理

    AOP代理对象的创建 AOP相关的代理对象的创建主要在applyBeanPostProcessorsBeforeInstantiation方法实现: protected Object applyBea ...

  5. Spring AOP 源码分析 - 拦截器链的执行过程

    1.简介 本篇文章是 AOP 源码分析系列文章的最后一篇文章,在前面的两篇文章中,我分别介绍了 Spring AOP 是如何为目标 bean 筛选合适的通知器,以及如何创建代理对象的过程.现在我们的得 ...

  6. Spring AOP 源码分析 - 创建代理对象

    1.简介 在上一篇文章中,我分析了 Spring 是如何为目标 bean 筛选合适的通知器的.现在通知器选好了,接下来就要通过代理的方式将通知器(Advisor)所持有的通知(Advice)织入到 b ...

  7. Spring AOP 源码分析 - 筛选合适的通知器

    1.简介 从本篇文章开始,我将会对 Spring AOP 部分的源码进行分析.本文是 Spring AOP 源码分析系列文章的第二篇,本文主要分析 Spring AOP 是如何为目标 bean 筛选出 ...

  8. Spring AOP 源码分析系列文章导读

    1. 简介 前一段时间,我学习了 Spring IOC 容器方面的源码,并写了数篇文章对此进行讲解.在写完 Spring IOC 容器源码分析系列文章中的最后一篇后,没敢懈怠,趁热打铁,花了3天时间阅 ...

  9. spring aop 源码分析(二) 代理方法的执行过程分析

    在上一篇aop源码分析时,我们已经分析了一个bean被代理的详细过程,参考:https://www.cnblogs.com/yangxiaohui227/p/13266014.html 本次主要是分析 ...

  10. spring AOP源码分析(一)

    对于springAOP的源码分析,我打算分三部分来讲解:1.配置文件的解析,解析为BeanDefination和其他信息然后注册到BeanFactory中:2.为目标对象配置增强行为以及代理对象的生成 ...

随机推荐

  1. Django-rest-framework 接口实现 版本控制 versioning

    版本控制 rest_framework 提供了 5 种版本控制 以及对应的 写法 url的 更改都可以 在 from rest_framework import versioning 中查看 Acce ...

  2. docker学习笔记(二)-dockerfile docker仓库

    dckerfile2这样写才对,不然打印的是hello $name 例子 登陆https://hub.docker.com 上面是提交到公共仓库 创建本地私有仓库 开启另外一个虚机,将重新构建上传镜像 ...

  3. Hive数据仓库工具安装

    一.Hive介绍 Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供简单SQL查询功能,SQL语句转换为MapReduce任务进行运行. 优点是可以通过类S ...

  4. EJB3.0之事务

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/aboy123/article/details/24586803 一 事务是什么 1 事务的概念 1. ...

  5. Google Colab 基本操作

    ## 上传 from google.colab import files uploaded = files.upload() for fn in uploaded.keys(): print('Use ...

  6. CSAPP:第八章 异常控制流1

    CSAPP:第八章 异常控制流1 关键点:异常 8.1 异常8.2 进程   现代系统通过使控制流发生突变来对这些情况做出反应,一般而言,我们把这些突变称为异常控制流(Exceptional Cont ...

  7. 一)surging 微服务框架使用系列之surging 的准备工作rabbitmq安装(转载 https://www.cnblogs.com/alangur/p/8339905.html)

    (一)surging 微服务框架使用系列之surging 的准备工作rabbitmq安装   (1)下载erlang: http://www.erlang.org/download/otp_win64 ...

  8. Spring Security(八):2.4.3 Project Modules

    In Spring Security 3.0, the codebase has been sub-divided into separate jars which more clearly sepa ...

  9. linux内存源码分析 - 内存压缩(实现流程)

    本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 概述 本文章最好结合linux内存管理源码分析 - 页框分配器与linux内存源码分析 -伙伴系统(初始化和申请 ...

  10. xxtea---单片机数据加密算法

    转:https://www.cnblogs.com/LittleTiger/p/4384741.html 各位大侠在做数据传输时,有没有考虑过把数据加密起来进行传输,若在串口或者无线中把所要传的数据加 ...