你会发现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注入的对象,然后就拿来直接用了。
简单的说一下今天讲课的这两位老师,两个人的讲课声音都小,在话筒前面讲话都声音这么小,
连坐在第一排的我都听的觉得声音小,后面的人就更甭提了,在这方面他们该向我学学,呵呵,
我虽然讲的贼差,但是声音洪亮,保证都听得到,今天上午就是个很好的例证(惭愧,今天糊里糊涂的
讲了一个小时,最得意的竟然是自己声音洪亮……)。
具体对比一下呢,陈老师说话是比张老师(是第一个试讲的张老师,不是张孝祥老师)清楚的,张老师声音
不但小,而且有的时候说着说着就没音了,我作为第一排的人尚且都这么觉得,后面的人就更是可想而知了,
迟早会有人提意见的,反正我是第一排无所谓。
跑题了,继续谈两个人的讲课风格,张老师虽然声音小而且有的字音不发出来,但是他的演讲沟通能力,尤其
是和学生之间目光的交流(这一点很重要),作为一个老师而言是绝对合格的;但是反观陈老师,整个过程他
的眼睛几乎就没有看学生,这可是老师讲课的大忌,看来他绝对是第一次讲,以前没怎么讲过……
以后如果我有机会上台讲的话,哪怕我眼睛盯着学生的头皮,我也不能总看着黑板或者电脑屏幕(据说李开复以前
初次讲课的时候也是这么干的,效果还不错),否则给人印象不会太好。
上面说的话应该不过分吧,只是说说对两位试讲老师的想法而已,我觉得我的判断还是没有错的,因为张老师的
试讲结束后大家外面交换想法的时候给这个老师的评价就是两个字“彪悍”,……彪悍的人生不需要解释啊,挺经典
的评价……至于第二位陈老师嘛,我相信绝大多数人肯定和我看法一样吧,多余的废话不说了,我又开始妄自评价
他人了,就此打住好了。