1、Spring的AOP编程

什么是AOP?  ----- 在软件行业AOP为Aspect Oriented Programming  也就是面向切面编程,使用AOP编程的好处就是:在不修改源代码的情况下,可以实现代码功能的增强

AOP的实现原理(掌握)

JDK的动态代理(注意JDK的动态代理只能对实现了接口的类产生代理)

/**

* Jdk的动态代理

* @author lilong

*/

public class JdkProxy implements InvocationHandler{

//要代理的对象

private CustomerDao customerDao;

public JdkProxy(CustomerDao customerDao){

this.customerDao = customerDao;

}

/**

* 生成代理对象的方法

* @return

*/

public CustomerDao createProxy(){

CustomerDao proxy = (CustomerDao) Proxy.newProxyInstance(customerDao.getClass().getClassLoader(), customerDao.getClass().getInterfaces(), this);

return proxy;

}

/**

* 增强的方法

*/

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

System.out.println("权限校验...");

return method.invoke(customerDao, args);

}

}

编写测试代码:

@Test

public void test1(){

CustomerDao customerDao = new CustomerDaoImpl();

JdkProxy jdkProxy = new JdkProxy(customerDao);

CustomerDao proxy = jdkProxy.createProxy();

proxy.save();

}

第二种代理方式Cglib方式(了解或者欣赏)

注意的是:Cglib可以对没有实现接口的类产生代理,生成子类来实现功能的增强

public class CglibProxy implements MethodInterceptor{

//要代理的对象

private LinkManDao linkManDao;

public CglibProxy(LinkManDao linkManDao) {

this.linkManDao = linkManDao;

}

public LinkManDao createProxy(){

//创建Cglib核心类

Enhancer enhancer = new Enhancer();

//设置父类

enhancer.setSuperclass(linkManDao.getClass());

//设置回调

enhancer.setCallback(this);

//生成代理

LinkManDao proxy = (LinkManDao) enhancer.create();

return proxy;

}

@Override

public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {

System.out.println("日志记录");

Object obj = methodProxy.invokeSuper(proxy, args);

return obj;

}

}

n  编写测试代码

@Test

public void test2(){

LinkManDao linkManDao = new LinkManDao();

CglibProxy cglibProxy = new CglibProxy(linkManDao);

LinkManDao proxy = cglibProxy.createProxy();

proxy.save();

}

2、Spring的AOP开发方式(xml方式)

其中相关术语的介绍

AOP开发所需要的jar介绍

n  AOP联盟的jar包:com.springsource.org.aopalliance-1.0.0.jar

n  Spring提供的AOP的jar包:spring-aop-4.2.4.RELEASE.jar

n  AspectJ的jar包:com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

n  Spring整合AspectJ的jar包:spring-aspects-4.2.4.RELEASE.jar

编写接口和实现类

ProductDao接口:

public interface ProductDao {

/**

* 持久层:产品保存

*/

public void save();

}

ProductDaoImpl实现类:

public class ProductDaoImpl implements ProductDao {

@Override

public void save() {

System.out.println("持久层:产品保存...");

}

}

配置相关类到Spring中

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="http://www.springframework.org/schema/beans

        http://www.springframework.org/schema/beans/spring-beans.xsd

        http://www.springframework.org/schema/context

        http://www.springframework.org/schema/context/spring-context.xsd">

<bean id="productDao" class="cn.itcast.dao.impl.ProductDaoImpl"></bean>

</beans>

编写切面类

/**

* 自定义切面类

* @author kevin

*/

public class MyAspectXml {

public void checkPrivilege(){

System.out.println("权限校验...");

}

}

配置切面类

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="http://www.springframework.org/schema/beans

        http://www.springframework.org/schema/beans/spring-beans.xsd

        http://www.springframework.org/schema/context

        http://www.springframework.org/schema/context/spring-context.xsd">

<bean id="productDao" class="cn.itcast.dao.impl.ProductDaoImpl"></bean>

<bean id="myAspectXml" class="cn.itcast.aspect.MyAspectXml"></bean>

</beans>

进行AOP配置

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:context="http://www.springframework.org/schema/context"

xmlns:aop="http://www.springframework.org/schema/aop"

xsi:schemaLocation="http://www.springframework.org/schema/beans

        http://www.springframework.org/schema/beans/spring-beans.xsd

        http://www.springframework.org/schema/context

        http://www.springframework.org/schema/context/spring-context.xsd

        http://www.springframework.org/schema/aop

        http://www.springframework.org/schema/aop/spring-aop.xsd">

<bean id="productDao" class="cn.itcast.dao.impl.ProductDaoImpl"></bean>

<bean id="myAspectXml" class="cn.itcast.aspect.MyAspectXml"></bean>

<!-- AOP配置 -->

<aop:config>

<!-- 配置切入点 -->

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))" id="pointcut1"/>

<!-- 配置切面 -->

<aop:aspect ref="myAspectXml">

<aop:before method="checkPrivilege" pointcut-ref="pointcut1"/>

</aop:aspect>

</aop:config>

</beans>

编写测试类

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration("classpath:applicationContext.xml")

public class TestAOP {

@Autowired

private ProductDao productDao;

@Test

public void test1(){

productDao.save();

}

}

总结:对切入点表达式语法进行总结

语法:[修饰符] 返回类型 包名.类名.方法名(形式参数)

常见写法:

n  execution(public * *(..))                                                                                      所有的public方法

n  execution(* set(..))                                                                                               所有set开头的方法

execution(* com.xyz.service.AccountService.*(..))                              AccountService类中的所有方法

execution(* com.xyz.service.*.*(..))                                                              com.xyz.service包下所有的方法

n  execution(* com.xyz.service..*.*(..))                                                           com.xyz.service包及其子包下所有的方法

3、Spring中AOP的通知类型

1.1.1.   前置通知:在方法执行之前增强。可以获得切入点信息。

<!-- AOP配置 -->

<aop:config>

<!-- 配置切入点 -->

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))" id="pointcut1"/>

<!-- 配置切面 -->

<aop:aspect ref="myAspectXml">

<!-- 前置通知 -->

<aop:before method="checkPrivilege" pointcut-ref="pointcut1"/>

</aop:aspect>

</aop:config>

public class MyAspectXml {

public void checkPrivilege(JoinPoint point){

System.out.println("权限校验..." + point);

}

}

1.1.2.   后置通知:在方法执行完之后增强。可以获取返回值信息。

/**

* 自定义切面类

* @author kevin

*/

public class MyAspectXml {

public void checkPrivilege(JoinPoint point){

System.out.println("权限校验..." + point);

}

public void afterReturn(Object result){

System.out.println("后置通知:" + result);

}

}

public class ProductDaoImpl implements ProductDao {

@Override

public void save() {

System.out.println("持久层:产品保存...");

}

public int delete(){

System.out.println("持久层:产品删除...");

return 100;

}

}

<!-- AOP配置 -->

<aop:config>

<!-- 配置切入点 -->

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))" id="pointcut1"/>

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.delete(..))" id="pointcut2"/>

<!-- 配置切面 -->

<aop:aspect ref="myAspectXml">

<!-- 前置通知 -->

<aop:before method="checkPrivilege" pointcut-ref="pointcut1"/>

<!-- 后置通知 -->

<aop:after-returning method="afterReturn" pointcut-ref="pointcut2" returning="result"/>

</aop:aspect>

</aop:config>

1.1.3.   环绕通知:在方法执行前后都进行增强。可以阻止方法的执行。

public class ProductDaoImpl implements ProductDao {

@Override

public void save() {

System.out.println("持久层:产品保存...");

}

public int delete(){

System.out.println("持久层:产品删除...");

return 100;

}

@Override

public void update() {

System.out.println("持久层:产品更新");

}

}

public class MyAspectXml {

public void checkPrivilege(JoinPoint point){

System.out.println("权限校验..." + point);

}

public void afterReturn(Object result){

System.out.println("后置通知:" + result);

}

public Object around(ProceedingJoinPoint joinpoint){

System.out.println("环绕前执行");

Object obj = null;

try {

obj = joinpoint.proceed();

} catch (Throwable e) {

e.printStackTrace();

}

System.out.println("环绕后执行");

return obj;

}

}

<!-- AOP配置 -->

<aop:config>

<!-- 配置切入点 -->

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))" id="pointcut1"/>

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.delete(..))" id="pointcut2"/>

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.update(..))" id="pointcut3"/>

<!-- 配置切面 -->

<aop:aspect ref="myAspectXml">

<!-- 前置通知 -->

<aop:before method="checkPrivilege" pointcut-ref="pointcut1"/>

<!-- 后置通知 -->

<aop:after-returning method="afterReturn" pointcut-ref="pointcut2" returning="result"/>

<!-- 环绕通知 -->

<aop:around method="around" pointcut-ref="pointcut3"/>

</aop:aspect>

</aop:config>

1.1.4.   异常抛出通知:当发生异常之后增强,可以获取异常信息。

public class ProductDaoImpl implements ProductDao {

@Override

public void save() {

System.out.println("持久层:产品保存...");

}

public int delete(){

System.out.println("持久层:产品删除...");

return 100;

}

@Override

public void update() {

System.out.println("持久层:产品更新");

}

@Override

public void find() {

System.out.println("持久层:查询");

int i = 10/0;

}

}

public class MyAspectXml {

public void checkPrivilege(JoinPoint point){

System.out.println("权限校验..." + point);

}

public void afterReturn(Object result){

System.out.println("后置通知:" + result);

}

public Object around(ProceedingJoinPoint joinpoint){

System.out.println("环绕前执行");

Object obj = null;

try {

obj = joinpoint.proceed();

} catch (Throwable e) {

e.printStackTrace();

}

System.out.println("环绕后执行");

return obj;

}

public void afterThrowing(Exception ex){

System.out.println("抛出异常通知:" + ex.getMessage());

}

}

<!-- AOP配置 -->

<aop:config>

<!-- 配置切入点 -->

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))" id="pointcut1"/>

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.delete(..))" id="pointcut2"/>

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.update(..))" id="pointcut3"/>

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))" id="pointcut4"/>

<!-- 配置切面 -->

<aop:aspect ref="myAspectXml">

<!-- 前置通知 -->

<aop:before method="checkPrivilege" pointcut-ref="pointcut1"/>

<!-- 后置通知 -->

<aop:after-returning method="afterReturn" pointcut-ref="pointcut2" returning="result"/>

<!-- 环绕通知 -->

<aop:around method="around" pointcut-ref="pointcut3"/>

<!-- 抛出异常通知 -->

<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="ex"/>

</aop:aspect>

</aop:config>

1.1.5.   最终通知:不管是否有异常,都会执行的

public class MyAspectXml {

public void checkPrivilege(JoinPoint point){

System.out.println("权限校验..." + point);

}

public void afterReturn(Object result){

System.out.println("后置通知:" + result);

}

public Object around(ProceedingJoinPoint joinpoint){

System.out.println("环绕前执行");

Object obj = null;

try {

obj = joinpoint.proceed();

} catch (Throwable e) {

e.printStackTrace();

}

System.out.println("环绕后执行");

return obj;

}

public void afterThrowing(Exception ex){

System.out.println("抛出异常通知:" + ex.getMessage());

}

public void after(){

System.out.println("最终通知");

}

}

<!-- AOP配置 -->

<aop:config>

<!-- 配置切入点 -->

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))" id="pointcut1"/>

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.delete(..))" id="pointcut2"/>

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.update(..))" id="pointcut3"/>

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))" id="pointcut4"/>

<!-- 配置切面 -->

<aop:aspect ref="myAspectXml">

<!-- 前置通知 -->

<aop:before method="checkPrivilege" pointcut-ref="pointcut1"/>

<!-- 后置通知 -->

<aop:after-returning method="afterReturn" pointcut-ref="pointcut2" returning="result"/>

<!-- 环绕通知 -->

<aop:around method="around" pointcut-ref="pointcut3"/>

<!-- 抛出异常通知 -->

<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="ex"/>

<!-- 最终通知 -->

<aop:after method="after" pointcut-ref="pointcut4"/>

</aop:aspect>

</aop:config>

注意:最终通知和后置通知的区别:最终通知,不管异常与否,都执行;而后置通知在异常时不执行。

4、Spring的AOP注解

4.1. 创建工程,引入jar包,创建核心配置文件

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="http://www.springframework.org/schema/beans

        http://www.springframework.org/schema/beans/spring-beans.xsd

        http://www.springframework.org/schema/aop

        http://www.springframework.org/schema/aop/spring-aop.xsd

        http://www.springframework.org/schema/context

        http://www.springframework.org/schema/context/spring-context.xsd">

<context:component-scan base-package="cn.itcast"></context:component-scan>

<!-- 开启自动代理注解 -->

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

</beans>

4.2. 创建接口和实现类

public interface ProductDao {

/**

* 持久层:产品保存

*/

public void save();

public int delete();

public void update();

public void find();

}

@Repository("productDao")

public class ProductDaoImpl implements ProductDao {

@Override

public void save() {

System.out.println("持久层:产品保存...");

}

public int delete(){

System.out.println("持久层:产品删除...");

return 100;

}

@Override

public void update() {

System.out.println("持久层:产品更新");

}

@Override

public void find() {

System.out.println("持久层:查询");

}

}

4.3. 编写切面类

@Component("myAspectAnnotation")

@Aspect

public class MyAspect {

@Before("execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))")

public void checkPrivilege(JoinPoint joinPoint){

System.out.println("权限校验..." + joinPoint.toString());

}

}

提示:此处的切面类可以不取id.

5、Spring的AOP 中注解通知

5.1. 前置通知

/**

* 前置通知

* @param joinPoint

*/

@Before("execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))")

public void checkPrivilege(JoinPoint joinPoint){

System.out.println("权限校验..." + joinPoint.toString());

}

5.2. 后置通知

@Aspect

public class MyAspect {

/**

* 前置通知

* @param joinPoint

*/

@Before("execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))")

public void checkPrivilege(JoinPoint joinPoint){

System.out.println("权限校验..." + joinPoint.toString());

}

@AfterReturning(value="execution(* cn.itcast.dao.impl.ProductDaoImpl.delete(..))",returning="result")

public void afterReturning(Object result){

System.out.println("后置通知:" + result);

}

}

5.3. 环绕通知

@Around("execution(* cn.itcast.dao.impl.ProductDaoImpl.update(..))")

public Object after(ProceedingJoinPoint joinpoint) throws Throwable{

System.out.println("环绕通知前增强");

Object obj = joinpoint.proceed();

System.out.println("环绕通知后增强");

return obj;

}

5.4. 异常通知

@AfterThrowing(value="execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))",throwing="ex")

public void afterThrowing(Exception ex){

System.out.println("抛出异常通知");

}

5.5. 最终通知

@After("execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))")

public void after(){

System.out.println("最终通知");

}

5.6. PointCut注解(了解)

作用:用于定义切入点表达式的一个注解。

@Component("myAspectAnnotation")

@Aspect

public class MyAspect {

/**

* 前置通知

* @param joinPoint

*/

@Before("execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))")

public void checkPrivilege(JoinPoint joinPoint){

System.out.println("权限校验..." + joinPoint.toString());

}

@AfterReturning(value="execution(* cn.itcast.dao.impl.ProductDaoImpl.delete(..))",returning="result")

public void afterReturning(Object result){

System.out.println("后置通知:" + result);

}

@Around("execution(* cn.itcast.dao.impl.ProductDaoImpl.update(..))")

public Object aroung(ProceedingJoinPoint joinpoint) throws Throwable{

System.out.println("环绕通知前增强");

Object obj = joinpoint.proceed();

System.out.println("环绕通知后增强");

return obj;

}

// @AfterThrowing(value="execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))",throwing="ex")

@AfterThrowing(value="MyAspect.pointcut()",throwing="ex")

public void afterThrowing(Exception ex){

System.out.println("抛出异常通知");

}

// @After("execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))")

@After("MyAspect.pointcut()")

public void after(){

System.out.println("最终通知");

}

@Pointcut("execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))")

public void pointcut(){

}

}

spring框架总结(03)重点介绍(Spring框架的第二种核心掌握)的更多相关文章

  1. Spring官方文档翻译——15.1 介绍Spring Web MVC框架

    Part V. The Web 文档的这一部分介绍了Spring框架对展现层的支持(尤其是基于web的展现层) Spring拥有自己的web框架--Spring Web MVC.在前两章中会有介绍. ...

  2. 是时候给大家介绍 Spring Boot/Cloud 背后豪华的研发团队了。

    看了 Pivotal 公司的发展历史,这尼玛就是一场商业大片呀. 我们刚开始学习 Spring Boot 的时候肯定都会看到这么一句话: Spring Boot 是由 Pivotal 团队提供的全新框 ...

  3. 【转帖】是时候给大家介绍 Spring Boot/Cloud 背后豪华的研发团队了。

    是时候给大家介绍 Spring Boot/Cloud 背后豪华的研发团队了. 2019/01/03 http://www.ityouknow.com/springboot/2019/01/03/spr ...

  4. Spring入门篇——第7章 Spring对AspectJ的支持

    第7章 Spring对AspectJ的支持 介绍Spring对AspectJ的支持 7-1 AspectJ介绍及Pointcut注解应用 实例 完成了在xml文件的配置 7-2 Advice定义及实例 ...

  5. 带你手写基于 Spring 的可插拔式 RPC 框架(一)介绍

    概述 首先这篇文章是要带大家来实现一个框架,听到框架大家可能会觉得非常高大上,其实这和我们平时写业务员代码没什么区别,但是框架是要给别人使用的,所以我们要换位思考,怎么才能让别人用着舒服,怎么样才能让 ...

  6. 关于如何介绍spring框架。

    一.介绍Spring 1.Spring是一个分层的JavaSE/EEfull-stack(一站式) 轻量级开源框架. 2.概念:轻量级的IOC(控制反转或者依赖注入).AOP(面向切面或者面向方面) ...

  7. Spring框架学习03——Spring Bean 的详解

    1.Bean 的配置 Spring可以看做一个大型工厂,用于生产和管理Spring容器中的Bean,Spring框架支持XML和Properties两种格式的配置文件,在实际开发中常用XML格式的配置 ...

  8. Spring4- 01 - Spring框架简介及官方压缩包目录介绍- Spring IoC 的概念 - Spring hello world环境搭建

    一. Spring 框架简介及官方压缩包目录介绍 主要发明者:Rod Johnson 轮子理论推崇者: 2.1 轮子理论:不用重复发明轮子. 2.2 IT 行业:直接使用写好的代码. Spring 框 ...

  9. Spring框架IOC和AOP介绍

    说明:本文部分内容参考其他优秀博客后结合自己实战例子改编如下 Spring框架是个轻量级的Java EE框架.所谓轻量级,是指不依赖于容器就能运行的.Struts.Hibernate也是轻量级的. 轻 ...

随机推荐

  1. 【Linux相识相知】yum的配置使用和程序包的编译安装

    在上一篇博客中,写到了如何使用rpm命令来安装.卸载软件等,但是大家都知道,各个软件包之间可能存在依赖关系,如果安装某个软件需要额外的依赖其他若干的包,那么我们就需要将其他额外的包一个一个的安装上去, ...

  2. IPsec_VPN实现技术【转载】

    GRE Tunnel GRE Tunnel(General Routing Encapsulation 通用路由封装)是一种非常简单的VPN(Virtual Private Network 虚拟专用网 ...

  3. Jquery的同步和异步请求

    1 异步请求:    1.1 $.ajax       $.ajax({                url : 'your url',                data:{name:valu ...

  4. Java课程设计——博客作业教学数据分析系统(201521123084 林正晟)

    #课程设计--博客作业教学数据分析系统(201521123084 林正晟) 1.团队课程设计博客链接 博客作业教学数据分析系统 2.个人负责模块或任务说明 学生登陆界面的前端实现和与数据库的连接 学生 ...

  5. Alpha个人总结

    一.我的问题: 1.第一章1.2.1 在软件的特殊性中说到,"大型软件有超过数百万行的源代码,上万个不同的文件,而软件工程师通常一次只能看到30-80行源代码,他们的智力.记忆力和常人差不多 ...

  6. 团队作业8——Beta 阶段冲刺7th day

    一.当天站立式会议 二.每个人的工作 (1)昨天已完成的工作(具体在表格中) 完善支付功能 (2)今天计划完成的工作(具体如下) 测试与正式发布 (3) 工作中遇到的困难(在表格中) 成员 昨天已完成 ...

  7. 1st_homework_SE--四则运算题目生成器

    0x00 Code 查询源代码及README请点此 0x01 需求分析 实现一个自动生成小学四则运算题目的命令行程序. 0x02 功能设计 主要功能为: 接受用户输入以便知道要出多少道题目python ...

  8. 201521123077 《Java程序设计》第5周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 举个小栗子: 右侧的四个类都实现了同一个接口,所以可以让游戏类的引用指向实现类的实例,根据不同类型的实现类可以表现出不同的特性 ...

  9. 201521123110《Java程序设计》第5周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 2. 书面作业 1.代码阅读:Child压缩包内源代码 1.1 com.parent包中Child.java文件能否编译通过? ...

  10. 201521123100 《Java程序设计》第3周学习总结

    1. 本周学习总结 初学面向对象,会学习到很多碎片化的概念与知识.尝试学会使用思维导图将这些碎片化的概念.知识组织起来.请使用纸笔或者下面的工具画出本周学习到的知识点.截图或者拍照上传. 2. 书面作 ...