目录

■前言

■省略部分

■代码构造

■运行效果

■具体代码

AspectTest

MyAspect   ★★★ @Aspect

AppConf   ★★★ @EnableAspectJAutoProxy

★★★★★★ @EnableAspectJAutoProxy

Child

Parent

Person

■其他配置

Maven

BackLog

■AOP相关术语说明

42.【Spring中这两个核心思想」都是一种设计模式(工厂,代理)

代理

43.静态代理:

44.动态代理

50.织入方式

49.AspectJ三种织入方式

■编写代码时,遇到的错误「com.sun.proxy.$Proxy21 cannot be cast」

但是,如果修改代理类的属性【EnableAspectJAutoProxy】指定为true

则不会出错。下面的这个类会被加载 CGLIB

@EnableAspectJAutoProxy

■更多 AOP 内容了解

Spring AOP 和AspectJ

ProceedingJoinPoint和JoinPoint



■前言

【Spring中这两个核心思想」都是一种设计模式(工厂,代理)

  IoC的思想基于工厂模式
  AOP的思想则是基于代理模式。

AspectJ是一个面向切面的框架,是目前最好用,最方便的AOP框架

【静态代理】编译时织入(特殊编译器实现)、类加载时织入(特殊的类加载器实现)

(常见的实现:JDK静态代理,AspectJ 。)

【动态代理】运行时增强(运行时织入),它不修改代理类的字节码,而是在程序运行时,运用反射机制,在【内存中】临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。
( 常见的实现:JDK、CGLIB、Javassist(Hibernate中使用的动态代理))

■省略部分

安装maven

安装lombook

■代码构造

■运行效果

14:09:56.035 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@4361bd48
14:09:56.064 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
14:09:56.154 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [C:\dev\MyJava001\target\classes\com\sxz\study\classload\Child.class]
14:09:56.155 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [C:\dev\MyJava001\target\classes\com\sxz\study\classload\Parent.class]
14:09:56.157 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [C:\dev\MyJava001\target\classes\com\sxz\study\aop\AspectTest.class]
14:09:56.161 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [C:\dev\MyJava001\target\classes\com\sxz\study\aop\MyAspect.class]
14:09:56.233 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
14:09:56.234 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
14:09:56.235 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
14:09:56.235 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
14:09:56.238 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.aop.config.internalAutoProxyCreator'
14:09:56.347 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'appConf'
14:09:56.387 [main] DEBUG org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory - Found AspectJ method: public java.lang.Object com.sxz.study.aop.MyAspect.around(org.aspectj.lang.ProceedingJoinPoint) throws java.lang.Throwable
14:09:56.390 [main] DEBUG org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory - Found AspectJ method: public void com.sxz.study.aop.MyAspect.before()
14:09:56.390 [main] DEBUG org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory - Found AspectJ method: public void com.sxz.study.aop.MyAspect.after()
14:09:56.391 [main] DEBUG org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory - Found AspectJ method: public void com.sxz.study.aop.MyAspect.afterReturning()
14:09:56.557 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'child'
父类--静态变量
父类--静态初始化块
子类--静态变量
子类--静态初始化块
父类--变量
父类--初始化块
父类--构造器
父类--变量
父类--初始化块
父类--构造器
14:09:56.589 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'parent'
父类--变量
父类--初始化块
父类--构造器
14:09:56.590 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'aspectTest'
14:09:56.591 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'myAspect'
14:09:56.600 [main] INFO com.sxz.study.aop.AspectTest - ===============================================
14:09:56.604 [main] INFO com.sxz.study.aop.MyAspect - ★★★★★around_1 startTime:0,endTime:0
14:09:56.604 [main] INFO com.sxz.study.aop.MyAspect - ★★before startTime:1642831796604,endTime:0
14:09:56.604 [main] INFO com.sxz.study.classload.Child - Children is playing
14:09:56.607 [main] INFO com.sxz.study.aop.MyAspect - ★★★afterReturning startTime:1642831796604,endTime:1642831796607,程序执行时间->3ms
14:09:56.607 [main] INFO com.sxz.study.aop.MyAspect - ★★★★after startTime:1642831796604,endTime:1642831796607,程序执行时间->3ms
14:09:56.607 [main] INFO com.sxz.study.aop.MyAspect - ★★★★★around_2 startTime:1642831796604,endTime:1642831796607
14:09:56.607 [main] INFO com.sxz.study.aop.AspectTest - ===============================================
14:09:56.607 [main] INFO com.sxz.study.classload.Parent - Parent is playing

---

■具体代码

AspectTest

package com.sxz.study.aop;import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;import com.sxz.study.classload.Person;
import com.sxz.study.conf.AppConf;import lombok.extern.slf4j.Slf4j;@Component
@Slf4j
public class AspectTest {public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext(AppConf.class);Person child = (Person)context.getBean("child");log.info("===============================================");child.play();log.info("===============================================");Person parent = (Person)context.getBean("parent");parent.play();}}

MyAspect   ★★★ @Aspect

package com.sxz.study.aop;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;import lombok.extern.slf4j.Slf4j;@Aspect
@Component
@Slf4j
public class MyAspect {private long startTime;private long endTime;/*** 声明一个切点*///@Pointcut("execution(* com.sxz.study.classload...*(..))")@Pointcut("execution(* com.sxz.study.classload.Child.play(..))")private void joinPoint(){// 这里的方法不会被执行log.info("●●●Pointcut startTime:{},endTime:{}" ,startTime, endTime);}/*** 程序执行之前*/@Before("joinPoint()")public void before(){this.startTime = System.currentTimeMillis();log.info("★★before startTime:{},endTime:{}" ,startTime, endTime);}/*** 程序执行之后*/@After("joinPoint()")public void after(){this.endTime = System.currentTimeMillis();log.info("★★★★after startTime:{},endTime:{},程序执行时间->{}ms" ,startTime, endTime,endTime-startTime);}/*** 程序执Ruturn之后*/@AfterReturning("joinPoint()")public void afterReturning(){this.endTime = System.currentTimeMillis();log.info("★★★afterReturning startTime:{},endTime:{},程序执行时间->{}ms" ,startTime, endTime,endTime-startTime);}@Around("joinPoint()")public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{log.info("★★★★★around_1 startTime:{},endTime:{}" ,startTime, endTime);// return proceedingJoinPoint.proceed();proceedingJoinPoint.proceed();log.info("★★★★★around_2 startTime:{},endTime:{}" ,startTime, endTime);return null;}}

AppConf   ★★★ @EnableAspectJAutoProxy

package com.sxz.study.conf;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;@Configuration
@ComponentScan(basePackages={"com.sxz.study.classload","com.sxz.study.aop"
})
@EnableAspectJAutoProxy
@Import({com.sxz.study.aop.MyAspect.class})/*@Aspect可以生效,相当于Configuration类作用,都是配置类*/
public class AppConf {}

★★★★★★ @EnableAspectJAutoProxy

1.在配置类上添加@EnableAspectJAutoProxy注解,开启注解版的AOP功能2.声明切面类:@Aspect表明这是一个切面类,
注:@Aspect是spring-annotation2/libs/com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar的注解。

EnableAspectJAutoProxy (Spring Framework 5.3.18 API)

ーーーー

Child

package com.sxz.study.classload;import org.springframework.stereotype.Component;import com.sxz.study.aop.MyAspect;import lombok.extern.slf4j.Slf4j;@Component
@Slf4j
public class Child extends Parent {        // 静态变量        public static String c_StaticField = "子类--静态变量";        // 变量        public String c_Field = "子类--变量";        // 静态初始化块        static {        System.out.println(c_StaticField);        System.out.println("子类--静态初始化块");        }        // 初始化块        {        System.out.println(p_Field);        System.out.println("父类--初始化块");        }        // 构造器        public Child() {        System.out.println("父类--构造器");        }public void play(){log.info("Children is playing");}
}

Parent

package com.sxz.study.classload;import org.springframework.stereotype.Component;import lombok.extern.slf4j.Slf4j;@Component
@Slf4j
public class Parent implements Person {        // 静态变量        public static String p_StaticField = "父类--静态变量";        // 变量        public String p_Field = "父类--变量";        // 静态初始化块        static {        System.out.println(p_StaticField);        System.out.println("父类--静态初始化块");        }        // 初始化块        {        System.out.println(p_Field);        System.out.println("父类--初始化块");        }        // 构造器        public Parent() {        System.out.println("父类--构造器");        }@Overridepublic void play() {log.info("Parent is playing");}       }

Person

package com.sxz.study.classload;public interface Person {void play();}

---

■其他配置

Maven

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>cn.sxz123</groupId><artifactId>Test001</artifactId><version>0.0.1-SNAPSHOT</version><name>Test001</name><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.10.RELEASE</version></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies></project>

BackLog

<?xml version="1.0" encoding="UTF-8"?>
<configuration><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern><![CDATA[%n[%d{yyyy-MM-dd HH:mm:ss.SSS}] [level: %p] [Thread: %t] [ Class:%c >> Method: %M:%L ]%n%p:%m%n]]></pattern></encoder></appender><appender name="LOG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><encoder><pattern><![CDATA[%n[%d{yyyy-MM-dd HH:mm:ss.SSS}] [level: %p] [Thread: %t] [ Class:%c >> Method: %M:%L ]%n%p:%m%n]]></pattern></encoder><file>J:/logs/sxz-web.log</file><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><fileNamePattern>logs/sports-web.-%d{yyyyMMdd}.%i.log</fileNamePattern><!-- 每天一个日志文件,当天的日志文件超过10MB时,生成新的日志文件,当天的日志文件数量超过totalSizeCap/maxFileSize,日志文件就会被回滚覆盖。 --><maxFileSize>10MB</maxFileSize><maxHistory>30</maxHistory><totalSizeCap>10GB</totalSizeCap></rollingPolicy> </appender><logger name="com.sxz" level="DEBUG" additivity="false"><appender-ref ref="STDOUT"/><appender-ref ref="LOG_FILE"/><!--<appender-ref ref="myAppender"/>--></logger><root level="INFO"><appender-ref ref="STDOUT"/><appender-ref ref="LOG_FILE"/><!--<appender-ref ref="mqAppender"/>--></root>
</configuration>

---

■AOP相关术语说明

切点Pointcut,切点代表了一个关于目标函数的过滤规则,后续的通知是基于切点来跟目标函数关联起来的。

  然后要围绕该切点定义一系列的通知Advice,如@Before、@After、@AfterReturning、@AfterThrowing、@Around等等定义的方法都是通知。其含义是在切点定义的函数执行之前、完成之后、正常返回之后、抛出异常之后以及环绕前后执行对应的切面逻辑。

  一个切点和针对该切点的一个通知共同构成了一个切面Advisor。对于一个方法,我们可以定义多个切点都隐含它,并且对于每个切点都可定义多个通知来形成多个切面,SpringAOP底层框架会保证在该方法调用时候将所有符合条件的切面都切入到其执行之前或之后或环绕。通知Advice的子类Interceptor或MethodInterceptor的类名更具体一些,包含了拦截器的概念。
---

一 概念理解
■  1     AOP的术语重在理解。  =======
Join Point:(连接点) Spring AOP中,join point就是一个方法。(通俗来讲就是起作用的那个方法,具体执行的方法)Pointcut:(切入点)  用来指定join point(通俗来讲就是描述的一组符合某个条件的join point)。通常使用pointcut表达式来限定joint point,Spring默认使用AspectJ pointcut expression language。Advice: 在join point上特定的时刻执行的操作,Advice有几种不同类型,下文将会讨论(通俗地来讲就是起作用的内容和时间点)。Introduction:给对象增加方法或者属性。Target object: Advice起作用的那个对象。AOP proxy: 为实现AOP所生成的代理。在Spring中有两种方式生成代理:JDK代理和CGLIB代理。Aspect: 组合了Pointcut与Advice,在Spring中有时候也称为Advisor。某些资料说Advisor是一种特殊的Aspect,其区别是Advisor只能包含一对pointcut和advice,但是aspect可以包含多对。AOP中的aspect可以类比于OOP中的class。Weaving:将Advice织入join point的这个过程。■ 2  Advice的类型 =======
Before advice:  执行在join point之前的advice,但是它不能阻止joint point的执行流程,除非抛出了一个异常(exception)。After returning advice: 执行在join point这个方法返回之后的advice。After throwing advice: 执行在join point抛出异常之后的advice。After(finally) advice: 执行在join point返回之后或者抛出异常之后的advice,通常用来释放所使用的资源。Around advice: 执行在join point这个方法执行之前与之后的advice。■ 3 两种代理 =======
Spring AOP是基于代理机制的。Spring AOP通过JDK Proxy和CGLIB Proxy两种方法实现代理。如果target object没有实现任何接口,那么Spring将使用CGLIB来实现代理。CGLIB是一个开源项目,它是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。如果target object实现了一个以上的接口,那么Spring将使用JDK Proxy来实现代理,因为Spring默认使用的就是JDK Proxy,并且JDK Proxy是基于接口的。这也是Spring提倡的面向接口编程。当然,你也可以强制使用CGLIB来进行代理,但是这样可能会造成性能上的下降。

---

42.【Spring中这两个核心思想」都是一种设计模式(工厂,代理)

  IoC的思想基于工厂模式
  AOP的思想则是基于代理模式。

工作中使用到的单词(软件开发)_sun0322-CSDN博客

代理

AOP 实现的关键就在于 AOP 框架自动创建的 AOP 代理,AOP 代理则可分为静态代理和动态代理两大类,其中静态代理是指使用 AOP 框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类,因此也称为编译时增强;而动态代理则在运行时借助于 JDK 动态代理、CGLIB 等在内存中“临时”生成 AOP 动态代理类,因此也被称为运行时增强

43.静态代理:

编译时增强,AOP 框架会在编译阶段生成 AOP 代理类,在程序运行前代理类的.class文件就已经存在了。

常见的实现:JDK静态代理,AspectJ 。

45.【静态代理】有:编译时织入(特殊编译器实现)、类加载时织入(特殊的类加载器实现)。

44.动态代理

运行时增强(运行时织入),它不修改代理类的字节码,而是在程序运行时,运用反射机制,
     在【内存中】临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,
     并且在特定的切点做了增强处理,并回调原对象的方法。
     常见的实现:JDK、CGLIB、Javassist(Hibernate中使用的动态代理)

46.【动态代理】有:jdk动态代理(基于接口来实现)、CGlib(基于类实现)。

47.JDK动态代理特点:

代理对象必须实现一个或多个【接口】
以接口形式接收代理实例,而不是代理类

48.CGLIB动态代理特点:

代理对象不能被final修饰
以类或接口形式接收代理实例

50.织入方式

---

49.AspectJ三种织入方式

---

■编写代码时,遇到的错误「com.sun.proxy.$Proxy21 cannot be cast」

java.lang.ClassCastException: com.sun.proxy.$Proxy21 cannot be cast to com.sxz.study.classload.Childat com.sxz.study.aop.AspectTest.main(AspectTest.java:19)

---

错误原因,没有使用接口接收

 public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext(AppConf.class);// Person child = (Person)context.getBean("parent");Person child = (Child)context.getBean("child");log.info("===============================================");child.play();log.info("===============================================");Person parent = (Person)context.getBean("parent");parent.play();}

---

但是,如果修改代理类的属性【EnableAspectJAutoProxy】指定为true

package com.sxz.study.conf;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;@Configuration
@ComponentScan(basePackages={"com.sxz.study.classload","com.sxz.study.aop"
})
@EnableAspectJAutoProxy(proxyTargetClass=true)
@Import({com.sxz.study.aop.MyAspect.class})/*@Aspect可以生效,相当于Configuration类作用,都是配置类*/
public class AppConf {}

则不会出错。下面的这个类会被加载 CGLIB

[Loaded com.sxz.study.classload.Child$$EnhancerBySpringCGLIB$$bcc03a27$$FastClassBySpringCGLIB$$c23bec39 from file:/C:/dev/MyJava001/target/classes/]

@EnableAspectJAutoProxy

@EnableAspectJAutoProxy引入了AspectJAutoProxyRegister.class对象 ,AspectJAutoProxyRegister给容器中注册一个AnnotationAwareAspectJAutoProxyCreator:

---

表示开启AOP代理自动配置,如果配@EnableAspectJAutoProxy表示使用cglib进行代理对象的生成;设置@EnableAspectJAutoProxy(exposeProxy=true)表示通过aop框架暴露该代理对象,aopContext能够访问.

从@EnableAspectJAutoProxy的定义可以看得出,它引入AspectJAutoProxyRegister.class对象,该对象是基于注解@EnableAspectJAutoProxy注册一个AnnotationAwareAspectJAutoProxyCreator,该对象通过调用AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);注册一个aop代理对象生成器。

---

springboot的注解@EnableAspectJAutoProxy讲解_码农的世界你不懂-CSDN博客_enableaspectjautoproxy

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {/*** Indicate whether subclass-based (CGLIB) proxies are to be created as opposed* to standard Java interface-based proxies. The default is {@code false}.*/boolean proxyTargetClass() default false;/*** Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}* for retrieval via the {@link org.springframework.aop.framework.AopContext} class.* Off by default, i.e. no guarantees that {@code AopContext} access will work.* @since 4.3.1*/boolean exposeProxy() default false;}

---

■更多 AOP 内容了解

Spring AOP 和AspectJ

https://www.baeldung.com/spring-aop-vs-aspectj

ProceedingJoinPoint和JoinPoint

JointPoint用法及与ProceedingJoinPoint 的关系 - 云+社区 - 腾讯云

ーーー

Java学习之「Spring + AspectJ 」相关推荐

  1. springcloud架构特点_你想了解的「Spring Cloud」都在这里

    前言: 之前我们已经了解了「什么是微服务?」,现在我们开始了解「微服务」关键字下比较热门的「Spring Cloud」- 一.传统架构发展史 部分引用自:从架构演进的角度聊聊Spring Cloud都 ...

  2. Java学习笔记-Day64 Spring 框架(二)

    Java学习笔记-Day64 Spring 框架(二) 一.控制反转IOC和依赖注入DI 1.控制反转IOC 2.依赖注入DI 3.Spring IOC容器 3.1.简介 3.2.实现容器 3.2.获 ...

  3. KESCI 迁移学习提供「借贷风险评估」解决方案的baseline改写,XGBOOST方法+SMOTE

    迁移学习提供「借贷风险评估」解决方案 大赛简介 金融场景是算法落地的重要场景.本次练习赛,我们聚焦于「借贷风险评估」问题.探索机器学习细分领域--迁移学习,在金融场景的更多可能性,以及其实践落地. 本 ...

  4. 下雨天,适合学「Spring Boot」

    北方的闷热,让不少小伙伴盼着下雨,前几天北京下了场大雨,杭州也紧跟这下了场雨,就在昨天原本还很闷热的天,突然就飘泼大雨了.今天也断断续续的下着小雨,一觉醒来已经是10点了.有句话说:懒惰是人的天性,最 ...

  5. 传统计算机视觉技术落伍了吗?不,它们是深度学习的「新动能」

    2019-12-24 11:40:47 选自arXiv 作者:Niall O' Mahony等机器之心编译 参与:魔王.张倩 深度学习崛起后,传统计算机视觉方法被淘汰了吗? 论文链接:https:// ...

  6. Google提出新型学习范式「Deep Memory」,或将彻底改变机器学习领域

    图源:pixabay 原文来源:arXiv 作者:Sylvain Gelly.Karol Kurach.Marcin Michalski.Xiaohua Zhai 「雷克世界」编译:嗯~是阿童木呀.K ...

  7. 清华本科生开发强化学习平台「天授」:千行代码实现,性能吊打国外成熟平台,刚刚开源...

    贾浩楠 发自 凹非寺 量子位 报道 | 公众号 QbitAI 江山代有才人出,开源一波更比一波强. 就在最近,一个简洁.轻巧.快速的深度强化学习平台,完全基于Pytorch,在Github上开源. 如 ...

  8. java学习day40(Spring)spring中的aop和基于XML以及注解的AOP配置

    第1章 AOP 的相关概念[理解] 1.1AOP 概述 1.1.1 什么是 AOP AOP :全称是 Aspect Oriented Programming 即:面向切面编程. 简单的说它就是把我们程 ...

  9. 类似婚礼纪的Java项目_「婚礼纪」婚礼纪 java面试 - seo实验室

    婚礼纪 我现在只是一个快2年经验的平凡的菜鸡boy 第一面架构师面试 1.简单介绍一下你经常使用的集合 3.arraylist和linklist的区别 4.map有用过吧,简单说一下 5.说一下Has ...

最新文章

  1. “上拉电阻与下拉电阻”通俗解读
  2. tflearn alexnet iter 10
  3. LWIP裸机环境下实现TCP与UDP通讯
  4. 服务器不安装Excel,实现导出Excel功能
  5. echarts热力背景图_Echarts 图表中设置背景图片
  6. 汉仪尚巍手书可以商用吗_【商用车维修】夏天修空调可以撑起全年修车收入的一半,你会了吗?...
  7. 最近幻影的两个ARP欺骗工具 挺不错的
  8. Visual Studio 2015出现Cannot find one or more components. Please reinstall the application.的问题解决
  9. 获取当前ip_write_ip_tcl命令你用过吗?
  10. for linux pdf转mobi_linux PDF转换为SWF
  11. java redis令牌桶_Redis令牌桶算法在限速中的应用
  12. web前端开发工程师的三种级别
  13. 计算机固态硬盘256g,1t(后悔买256g的固态硬盘了)
  14. 保研夏令营面试、考研复试自我介绍、个人展示模板与撰写注意事项
  15. stm32-DHT11原理及代码解读
  16. vue 之url拼接 根据选择条件动态修改url地址
  17. 如何创建一个Facebook群组
  18. 【人生杂谈】 - 金钱/名利 贫穷/富贵 健身房定律
  19. python初中级开发面经(持续更新2020-3-7)
  20. idea不显示Services工具栏解决办法

热门文章

  1. maven编译报程序包不存在_宝马730i空调不制冷,报冷却剂压缩机当前存在故障
  2. html5中秋博饼,2020年中秋博饼优秀作文(精选5篇)
  3. RuntimeWarning: coroutine ‘ClientResponse.text‘ was never awaited self._context.run(self._callback)
  4. 中国智能卡市场的新机会
  5. 关于敏捷方法的一次沟通记录
  6. java判断题及答案_Java面试题及解析(判断题)
  7. python dd 合并二进制文件_马克的Python学习笔记#数据编码与处理 5
  8. 竞价推广经验分享 账户的搭建方法
  9. nginx基本配置与参数说明-【转】
  10. 2016年04月28日-统一沟通之OCS 2007 R2-公开课-通知