3月1日——培训第68天

你会发现JUnit源码被分配到6个包中:
junit.awtui、junit.swingui、junit.textui、junit.extensions、
junit.framework、junit.runner。
其中前三个包中包含了JUnit运行时的入口程序以及运行结果显示界面,
它们对于JUnit使用者来说基本是透明的。

junit.runner包中包含了支持单元测试运行的一些基础类以及自己的类加载器,
它对于JUnit使用者来说是完全透明的。

剩下的两个包是和使用JUnit进行单元测试紧密联系在一起的。其中junit.framework包
含有编写一般JUnit单元测试类必须是用到的JUnit类;而junit.extensions则是对
framework包在功能上的一些必要扩展以及为更多的功能扩展留下的接口。

。Assert类提供了JUnit使用的一整套的断言,这套断言都被TestCase继承下来,
Assert也就变成了透明的。Test接口是为了统一TestCase和TestSuite的类型;
而TestCase里面提供了运行单元测试类的方法;在TestSuite中则提供了加载单元测试类,
检验测试类格式等等的方法。TestResult故名思意就是提供存放测试结果的地方,
但是在JUnit中它还带有一点控制器的功能。TestListener接口抽象了所有测试监听者的行为,
他包括两个添加错误和失败的方法,开始测试和结束测试的方法。在JUnit框架中有两个类实现了这个接口,
一个负责结果打印的ResultPrinter类,一个是所有TestRunner的基础类BaseTestRunner类


从9点开始到10点10分是我讲Junit的源代码,主要分析一下测试用例和测试包作为传入参数的执行流程,
以及带main函数和不带main函数有何区别,还有junit里面的设计模式的具体体现,就这么点东西,越讲
脑子越乱,讲到最后都不知道自己在说什么了,讲课这玩意儿,太难了,一不小心就是千夫所指……讲完后
得到的田老师的评价————“声音洪亮”。这个这个……我就当它为夸奖吧,呵呵……
-------------------------------------------------------------------------------


ApplicationContext的事件机制:

Spring允许程序运行中发布事件,并且由事件监听器处理事件。
ContextRefreshedEvent
ContextClosedEvent
RequestHandledEvent

上面这三个是Spring定义的系统事件。

Spring中的事件必须扩展自ApplicationEvent
ApplicationEvent仅包含有一个具有一个参数的构造函数,因此子类必须主动调用。
public class MyEvent extends ApplicationEvent {
 public MyEvent(Object source) {
  super(source);
 }
}

事件发布是通过ApplicationContext完成的,方法是publishEvent(ApplicationEvent event)
ApplicationContext c = new ClassPathXmlApplicationContext("bean.xml");
c.publishEvent(new MyEvent(this));

Spring中的所有监听器都必须实现ApplicationListener,并定义onApplicationEvent方法。
public class MyListener implements ApplicationListener {
 public void onApplicationEvent(ApplicationEvent arg0) {
  // TODO Auto-generated method stub
  ……
 }
}
事件监听器也必须向ApplicationContext注册,即:
<bean id="eventListener" class="mybeans.MyListener" />
--------------------------------------------------------------------
ApplicationEvent这个抽象类是没有抽象方法的,一个抽象类可以没有抽象方法,
但是有抽象方法的类一定是抽象类。

这个抽象类有一个非空的构造方法。
例子:

package bean ;

public class MyEvent extends ApplicationEvent
{
 public MyEvent(Object obj)
 {
  super(obj);
 }
}


package bean ;

public class MyListener implements ApplicationListener
{
 public void onApplicationEvent(ApplicationEvent arg0)
 {
  System.out.println("in my listener");
 }
}


package bean ;

public class Another implements ApplicationListener
{
 public void onApplicationEvent(ApplicationEvent arg0)
 {
  System.out.println("in another listener");
 }
};
//监听器写完后必须注册到容器中。

<bean id="my" class="bean.MyListener" />

<bean id="another" class="bean.AnotherListener" />
public static void main(String[] args)
{
 ClassPathXmlApplicationContext context =
  new ClassPathXmlApplicationContext("bean.xml");
 context.publishEvent(new MyEvent(context));
}

只要实现了ApplicationListener,就会被当作是观察者。两个监听器都打印出了信息
当然如果你只是想对某个监听器感兴趣的话,可以:

public void onApplicationEvent(ApplicationEvent arg0)
{
 if(arg0 instanceof MyEvent)
 {
  System.out.println("in another listener");
 }
}
就会只监听上面的打印信息。

============================================================================

下面说说AOP,面向切面

AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向方面编程。
它将分布在各个类中具有相同功能的代码片段整合到一起,由单独的功能模块完成,
不仅减少了代码的重复量,降低了耦合,也提高了代码的可维护性。
不要认为AOP会取代OOP,它只是OOP的补充。但就像当年的OOP一样,它很可能引发一场软件产业的革命。

切面(Aspect):从对象中抽取出来的交叉功能模块(比如日志输出功能)
 通知(Adivice):切面的具体实现
连接点(Joinpoint):可以插入方法的地方
 切入点(Pointcut):连接点的集合(实际切入通知的地方)
引入(Introduction):为已经存在的类添加新方法和属性(动态的扩展新的方法和属性)

目标对象(Target Object):
 被通知的对象
代理(AOP Proxy):
 由AOP框架创建的目标对象的代理对象
织入(Weaving):
 将通知与目标对象结合在一起,生成新的代码片段的过程

AOP是通过代理模式实现的。代理模式实现可以通过java中的Proxy,或是使用CGLIB
Spring使用两种机制实现AOP技术,一是使用java的动态代理,即java.lang.reflect.Proxy类
创建代理。
二是使用CGLIB库自动生成目标对象的子类,同时织入通知。
动态代理要求目标对象必须要实现接口(只有这样才能创建代理),而CGLIB则没有这种限制。

 

目前,人们使用传统语言对核心业务进行编程,对横切面的功能模块则使用面向切面的编程语言。
面向切面的编程语言可以是已有编程语言的扩展,如AspectJ,AspectC++,AspectC,
AspectC#,Apostle等,或是一种新的语言

Java语言可以使用反射(Reflection),基于动态代理(Dynamic Proxy)或其它机制的拦截框架,基于元数据(Metadata)的操作,以及类载入时对字节码的操作
等来实现AOP。

目前无法纯粹的用语言实现彻底的AOP


由于目前AOP还没有完全的统一标准,因此实现出来的AOP框架也是多种多样的,为此人们成立了一个
AOP联盟,用于统一这种混乱局面
Aop Alliance是由多个AOP项目组成的组织,定义一套AOP标准的Java接口,以方便各种AOP框架可以互通。
Spring也是以这套接口为基础的

-----------------------------------------------------------------------------------

说一下代理机制:java.lang.reflect.Proxy类就是用来实现代理模式的……

新建一个工程:

先建立一个代理类:

public class MyInvocationHandler implements InvocationHandler
{

 private Object target = null ;

 public MyInvocationHandler(Object obj)
 {
  target = obj ;
 }
 //第一个参数:由proxy生成的代理对象
 //第二个参数:调用的是哪个方法
 //第三个参数:调用的方法的参数

 //我们的目的是代理一个ArrayList
 public Object invoke(Object proxy , Method method, Object[] args)
  throws Throwable
 {
  
  System.out.println(method.getName()+" is running!!");
  Object result = method.invoke(target,args); //运行被代理的对象的对应的方法
  //其实上下两个打印语句可以换成其他具体的方法,也就是所谓的切面了。
  System.out.println(method.getName()+" end!");
  return result ;
 }
}


public static void main(String[] args)
{
 List l = new ArrayList();
 InvocationHandler ih = new MyInvocationHandler(l);
 List lp = (List)Proxy.newProxyInstance(l.getClass().getClassLoader(),
  new Class[]{List.class},ih);

 //对代理对象进行操作
 lp.add("dsfsdf");
 lp.add("asdf");

 Iterator it = l.iterator();

 //对被代理的对象进行迭代,会发现上面对代理对象的操作影响到了被代理的原始对象……
 while(it.hasNext())
 {
  System.out.println(it.next());
 }

}
==============================================================

创建目标对象,目标对象必须是实现了某种接口的。
创建通知,通知定义了一个切面的具体逻辑。
向上下文注册

创建目标对象:
public class J2eeCourse implements Course {
 String name;
 public J2eeCourse(String name) {
  this.name = name;
 }
 public void process(Teacher teacher) {
  System.out.println(name + "is in process, and the teacher is"
     + teacher.getName());
  teacher.giveClass();
 }

 public String getName() {
  return name;
 }
}

使用Java动态代理机制实现的AOP必须要将目标对象中的方法声明在一个接口中:
public interface Course {
 public void process(Teacher teacher);
 public String getName();
}

前置通知:切入到方法的前面

此处创建的是前置通知:
public class CourseAdvice implements MethodBeforeAdvice {

 public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
  
  Course course = (Course)arg2;
  Teacher teacher = (Teacher) arg1[0];
  System.out.println("hi, teacher " + teacher.getName() +
    ", there is a " + course.getName()+
    ", do you have time to listener this class?");
 }
 
}

<beans>
   <bean id="courseTarget" class="aop.J2eeCourse">
     <constructor-arg  value=”j2ee“/>
   </bean>
   <bean id="rod" class="aop.TeacherRod">
     <constructor-arg value=“Rod Johnson”/>
   </bean>
   <bean id="advice" class="aop.CourseAdvice"/>
   <bean id="course" class="org.springframework.aop.framework.ProxyFactoryBean">
     <property name="proxyInterfaces" value=“aop.Course”/>
     <property name="interceptorNames">
       <list><value>advice</value></list>
     </property>
     <property name="target” ref"courseTarget" />
   </bean>
</beans>


除MethodInterceptor(环绕通知)是由aop alliance定义以外,其余接口
均位于org.springframework.aop中
MethodInterceptor位于org.aopalliance.intercept包中,因此如果需要
使用这个接口,必须导入aopalliance的jar文件。


=======================================================================

例:加入spring.jar和commons-logging.jar以及bean.xml等。

接口:
package aop ;

public interface Test
{
 public void showMsg(String msg);
 public void another();
}

目标对象:
package aop ;
//前置通知将切入到这两个方法里面……
public class TestBean implements Test
{
 public void showMsg(String msg)
 {
  System.out.println(msg);
 }

 public void another()
 {
  System.out.println("in another");
 }
};

建立一个前置通知:

package aop ;

public class LogAdvice implements MethodBeforeAdvice
{
 public void before(Method arg0,Object[] arg1,Object arg2)
  throws Throwable
 {
  //这就是一个切片了……
  System.out.println("Object "+arg2.getClass()+"'s method "
    +arg0.getName()+" is running!");
 }
}

bean.xml:

<beans>
 <bean id="testTarget" class="aop.TestBean" /> //注册目标对象
 <bean id="advice" class="aop.LogAdvice" />//注册通知
 <bean id="test" class="org.springframework.aop.framework.ProxyFactoryBean">
 //下面利用ProxyFactoryBean中的setter方法来依赖注入
  <property name="target" ref="testTarget" />
  //由于setTestTarget方法返回的是Object类型,所以上面用ref而不用value
  //接下来告诉容器要实现什么接口!
  <property name="proxyInterfaces" value="aop.Test" />
  //接下来是你要切入的通知是谁
  <property name="interceptorNames">
   <list> //由于setInterceptorNames传入的是数组,所以要用list
    <value>advice</value>
   </list>
  </property>
 </bean>
</beans>

public static void main(String[] args)
{
 ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
 Test test = (Test)context.getBean("test"); //去得到代理的对象,也就是ProxyFactoryBean
 test.showMsg("hello");
 test.another();
}

这样,一个简单的AOP就完成了。但是注意,上面这个AOP是没有切入点的,也就是说,showMsg和another两个
方法在执行之前都会被插入前置信息,切入点是可以让我们自由选择将前置信息插入到哪个方法之前。
=========================================================================================
今天晚上和明天晚上都有老师要来试讲,以后的班都会有多个老师来管理,每个老师负责一部分,张老师负责全局监督,
大概是这样吧……


下面说说切入点:
切入点用于定义通知加入到目标对象中的位置,没有切入点通知将被应用于所有方法上。
Spring以org.springframework.aop.PointCut来定义切入点。
切入点分为两类,即静态切入点和动态切入点
静态切入点下,通知总被执行,动态切入点下,通知依据运行时的参数决定通知是否需要执行。

Advisor:
由于ProxyFactoryBean只接受Advice和Advisor类型的Interceptor(参照API),所以
不能直接应用PointCut到ProxyFactoryBean上
Advisor是Spring AOP中特有的概念,它持有通知,并决定通知是否应用到当前实例上。
由于切入点是决定通知是否应用的重要依据,故PointcutAdvisor中持有通知和切入点,
并依据切入点决定是否应用通知。

public interface Advisor {
 Advice getAdvice();
 boolean isPerInstance();
}

public interface PointcutAdvisor extends Advisor {
 Pointcut getPointcut()
}
由于PointcutAdvisor继承自Advisor,因此可以当成
Interceptor使用。


一个是通知,一个是切入点,这两个应用在一个对象里面后就是AOP了。
----------------------------------------------------
内置切入点:

静态切入点
StaticMethodMatcherPointcut(抽象)
NameMatchMethodPointcut-名字匹配
JdkRegexpMethodPointcut-JDK与此同时表达式
Perl5RegexpMethodPointcut -Perl 5正则表达式
动态切入点
DynamicMethodMatcherPointcut (抽象)
ControlFlowPointcut


这样就可以简单修改上面的配置文件,只切入showMsg方法,而不切入another
方法了。

bean.xml:

<beans>
 <bean id="testTarget" class="aop.TestBean" /> //注册目标对象
 <bean id="advice" class="aop.LogAdvice" />//注册通知

 <bean id="advisor"
  class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
  
  <property name="advice" ref="advice" /> //设置通知
  <property name="mappedName" value="showMsg" />//设置切入的方法
 </bean>

 <bean id="test" class="org.springframework.aop.framework.ProxyFactoryBean">
 //下面利用ProxyFactoryBean中的setter方法来依赖注入
  <property name="target" ref="testTarget" />
  //由于setTestTarget方法返回的是Object类型,所以上面用ref而不用value
  //接下来告诉容器要实现什么接口!
  <property name="proxyInterfaces" value="aop.Test" />
  //接下来是你要切入的通知是谁
  <property name="interceptorNames">
   <list> //由于setInterceptorNames传入的是数组,所以要用list
    <value>advisor</value>
   </list>
  </property>

  //特别注意,其实上面的也可以写为:
  //<property name="interceptorNames" value="advisor" />
  //也是没有问题的,因为传入的参数中的数组仅有一个元素,所以可以像上面
  //那样去写
 </bean>
</beans>


========================================================================

下面看看正则表达式匹配:

在上面的bean配置文件中加上下面的配置:
<bean id="advisor1"
  class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
  
 <property name="advice" ref="advice" /> //设置通知
 <property name="pattern">//设置切入的方法
 //使用正则表达式匹配切片切入的方法,匹配的是“包名加上类名加上方法名”
  <value>^aop/.Test/.showMsg$</value>
 //注意这里必须要使用接口的showMsg,不要使用具体实现类的showMsg方法!!
 //上面的^和$还有那个/是可以不加的
 </property>
</bean>

然后再修改工厂bean的设置如下,其实改的就是最后一个interceptorNames属性值:

<bean id="test" class="org.springframework.aop.framework.ProxyFactoryBean">
 <property name="target" ref="testTarget" />  
 <property name="proxyInterfaces" value="aop.Test" />  
 <property name="interceptorNames" value="advisor1"/> 
</bean>


============================================================================

AOP就说到这里,下面是Spring的数据层,Spring的数据层是十分繁杂的……

Spring提供了对数据层的广泛支持,这包括:
传统JDBC
Hibernate
JDO
Oracle TopLink
Apache OJB
iBATIS SQL Map

Spring JDBC方式采用模板与回调相结合的模式,核心类是JdbcTemplate。

使用JDBC方法处理DAO,必须要知道数据源DataSource。
Spring DAO层中,获取数据源方法有三种:
通过JNDI(比如Tomcat配置数据源,需要JNDIFactory)
使用第三方的连接池(比如那个dbcp包)
使用DriverManagerDataSource(没有连接池在里面,主要用于测试)

在api中,JdbcTemplate位于org.springframework.jdbc包里面
只要是具体类并且有相应的setter方法就可以通过依赖的关系注入容器

org.springframeword.jdbc.datasource包里面有那个DriverManagerDataSource

配置文件:

数据源bean:
<bean id="dataSource"
 class="org.springframework.jdbc.datasource.DriverManagerDataSource">

 <property name="driverClassName">
  <value>com.mysql.jdbc.Driver</value>
 </property>
 <property name="url">
  <value>jdbc:mysql:///j2ee</value>
 </property>
 <property name="username">
  <value>root</value>
 </property>
 <property name="password">
  <value>root</value>
 </property>
</bean>

jdbcTemplate:
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
 <property name="dataSource" ref="dataSource" /> 
</bean>

然后上面这个jdbcTemplate就可以注入到javaBean里面了。

--------------------------------------------------------------

下面这个方法是个回调方法,所谓回调方法,就是你自己定义出来给JdbcTemplate去使用,而是定义
给你自己使用的,doPost方法也是回调方法。
public class QueryStatementCallBack implements StatementCallback
{
 private String sql ;

 public QueryStatementCallBack(String sql)
 {
  this.sql = sql ;
 }

 public Object doInStatement(Statement stmt)
  throws Exception
 {
  ResultSet rs = stmt.executeQuery(sql) ;
  //对结果集进行迭代
  ArrayList list = new ArrayList() ;
  ResultSetMetaData rsmd = rs.getMetaData();
  int count = rsmd.getColumnCount() ;

  while(rs.next)
  {
   Map map = new HashMap() ;
   for(int i = 1 ; i <= count ; i ++)
   {
    map.put(rsmd.getColumnName(i),rs.getObject(i)) ;
   }
   list.add(map);
  }

  rs.close() ;
  //这里所有的异常都被这个方法抛出去给Spring框架了
  return list ;
 }
}

 

public static void main(String[] args)
{
 ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
 JdbcTemplate tem = (JdbcTemplate)context.getBean("jdbcTemplate");
 List list = (List)tem.execute(new QueryStatementCallBack("select * from courses"));

 //List list = tem.queryForList("select * from courses");
 //注意上面被注释掉的语句可以取代下面的
 //“List list = (List)tem.execute(new QueryStatementCallBack("select * from courses"));”

 Iterator it = list.iterator() ;
 while(it.hasNext())
 {
  System.out.println(it.next()) ;
 }
}


-----------------------------------
下面这个是通过依赖注入的方式实现了一个CourseBean
public class CourseBean
{
 private int id ;
 private String name ;
 private JdbcTemplate jdbcTemplate ;
 
 //加入getter和setter方法

 public void save()
 {
  jdbcTemplate.update("insert into courses(course_name) values('"
       +name+"')");
 }
}

在bean.xml中使用依赖注入,将已经注册好的JdbcTemplate,也就是上面的
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
 <property name="dataSource" ref="dataSource" /> 
</bean>

通过依赖注入的方式,也即<property name="" ref="jdbcTemplate">的方式注册到
CourseBean的配置中去,这样就可以用类似下面的方式来使用:

  Resource res = new ClassPathResource("bean.xml");
  XmlBeanFactory factory = new XmlBeanFactory(res);
  CourseBean course = (CourseBean)factory.getBean("course");

  这样得到了一个CourseBean的实例,然后可以直接使用jdbcTemplate了。
========================================================================

getConnection()来获得连接,然后,stmt = createStatement创建语句,callback再去调用
doInStatement(stmt),返回一个Object ,最后release()
这也就是一个回调方法的大概过程,周边的事情,比如关闭连接之类,spring都给你做好了。

===============================================================================

晚上是一个陌生的老师讲课,本来说好是6点40的,结果提前了10多分钟,我差点就迟到……:

Linux做java开发;uml工具的使用

操作系统:windows、unix、linux
unix操作系统是sun公司做的(中低端的)
惠普是做的hp-ux
ibm做的是aix

bsd系列操作系统:freebsd、openbsd、netbsd

从稳定性上来看,linux和unix差别不大,linux分类主要有:redhat、suse、ul

redhat:个人版和企业版两个版本,个人版用的较多的是7.2 7.3 8和9 版本
企业版主要是as系列,也就是高级服务器,主要是2.1版、3和4版本

个人版一般是用8或9版本,个人版最好装9,企业版最好是装3或4版本。

安装:可以从光盘装、硬盘装、或是通过网络安装(nfs、http、ftp)

自己装的话,最好装成虚拟机的形式:vmware或vpc

基本命令:


远程管理工具:

命令行管理工具:(telnet:端口是23,ssh:secure shell)
图形界面:vnc


配置java环境:安装jdk

tomcat:weblogic resin jboss

安装方法:源代码安装、二进制安装rpm(redhat package management)

二进制安装较为简单,如果是服务器的话应该使用源代码安装。

源代码安装是通过make,也就是类似于ant的方式

rpm -ivh 命令用来安装具体的文件

i:install
v:verbose
h:hash

配置环境:和windows一样,针对系统和针对当前用户,添加环境变量可以针对用户,也可以
针对系统变量,linux中也是一样的。

如果是针对个人:那么就是要对用户的配置文件做更改
如果是对系统:就是系统的配置文件
---------------------------------------------------------------------------
今天这位老师主要是来试讲的,不是来讲课的,所以演示的内容也比较的多,一会儿还有一位老师来试讲
Spring,大概他们以后都会是传智播客的讲师吧,利用工作之余的时间来讲课确实不错,和接私活一样
的性质吧。

现在是张老师讲ajax,暂时先讲5分钟,那个试讲spring的老师很快就到……

传统方式是浏览器发送请求,工作流程是:显示页面-》提交请求-》等待响应-》显示新页面,这就有不流畅的
问题,其实ajax就是让javascript发送和接收请求的同时让我们用户仍能对网页进行操作。

----------------------------------------------------------------------------------
下面来的这位是陈老师,是位写书的能手,几乎java的框架什么的都被他写遍了,今天来没有带电脑,只是ppt
而已,暂时用张老师的电脑。

这位老师的名字是陈天河,毕业于1999年,一直从事java开发工作至今,主要擅长开源框架,apache的大部分组件
都用过,但是对ejb不是太熟悉,今天来主要是讲一下Spring的入门知识。

AOP、IOC、DI
AOP是面向切面的编程,目的是实现系统的松散耦合,使我们可以从另一个角度去优化程序的结构。
比如url请求先到Tomcat,然后到ActionServlet,然后再到RequestProcessor,然后到Action,
最终进入数据库操作,然后返回生成jsp页面响应。切面编程可以在上述流程中做出一些横向的处理。
比如对所有请求的一种通用的处理,类似于Filter的东西,是一种类似于横向的思想。

Ioc:控制反转:解决各个组件之间的依赖关系,提高组件的重用几率。

DI:依赖注入(其实就是实现Ioc的一种方法)

Ioc容器是Spring的核心

核心包:org.springframework.beans
    org.springframework.context
核心类:BeanFactory
    AplicationContext

元数据的三种配置方法:xml、属性文件、使用Spring的API编程来实现。
一般都用xml配置文件……

简单的格式略,上课说过很多次了。
-----------------------------------------------------------------
陈老师的试讲结束,感觉他准备的不是很充分,虽然写书一把手,但是说到讲课……有待提高了,
张孝祥老师还要总结一些东西……

到底什么是控制反转?
其实就是我这个类需要的资源被反转了,这种反转主要用在依赖注入上,把我需要的资源注入进来。
比如数据源作为成员变量放到一个类里面,同时将它注册到Spring中的配置文件里面,通过getBean方法
得到这个数据源,也就是Spring注入的对象,然后就拿来直接用了。


简单的说一下今天讲课的这两位老师,两个人的讲课声音都小,在话筒前面讲话都声音这么小,
连坐在第一排的我都听的觉得声音小,后面的人就更甭提了,在这方面他们该向我学学,呵呵,
我虽然讲的贼差,但是声音洪亮,保证都听得到,今天上午就是个很好的例证(惭愧,今天糊里糊涂的
讲了一个小时,最得意的竟然是自己声音洪亮……)。

具体对比一下呢,陈老师说话是比张老师(是第一个试讲的张老师,不是张孝祥老师)清楚的,张老师声音
不但小,而且有的时候说着说着就没音了,我作为第一排的人尚且都这么觉得,后面的人就更是可想而知了,
迟早会有人提意见的,反正我是第一排无所谓。

跑题了,继续谈两个人的讲课风格,张老师虽然声音小而且有的字音不发出来,但是他的演讲沟通能力,尤其
是和学生之间目光的交流(这一点很重要),作为一个老师而言是绝对合格的;但是反观陈老师,整个过程他
的眼睛几乎就没有看学生,这可是老师讲课的大忌,看来他绝对是第一次讲,以前没怎么讲过……
以后如果我有机会上台讲的话,哪怕我眼睛盯着学生的头皮,我也不能总看着黑板或者电脑屏幕(据说李开复以前
初次讲课的时候也是这么干的,效果还不错),否则给人印象不会太好。

上面说的话应该不过分吧,只是说说对两位试讲老师的想法而已,我觉得我的判断还是没有错的,因为张老师的
试讲结束后大家外面交换想法的时候给这个老师的评价就是两个字“彪悍”,……彪悍的人生不需要解释啊,挺经典
的评价……至于第二位陈老师嘛,我相信绝大多数人肯定和我看法一样吧,多余的废话不说了,我又开始妄自评价
他人了,就此打住好了。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值