2009年7月22日 #
2004年,Tantek被不同瀏覽器下默認(rèn)樣式的差異給搞煩了,于是寫了一個undohtml.css,這也就誕生了世界上第一份reset.css。
CSS Negotiation and a Sanity Saving Shortcut. * { margin: 0; padding: 0 } 的學(xué)名是Global White Space Reset. 從原文中可以看出這個方法剛問世時是非常火爆的,并且作者建議一定要先破后立,要將清掃差異和重置默認(rèn)樣式結(jié)合起來,這樣才是正確的做法。
為何Global White Space Reset當(dāng)初風(fēng)光一時,如今卻黯然銷魂?* { margin: 0; padding: 0 }的成功之處在于,管你三七二十八,統(tǒng)統(tǒng)抹平,人人生而平等!然而其失敗之處也正是因?yàn)槠渫μ螅m然搗了蜂窩得了蜜,卻惹來群蜂追尾,麻煩無限(因?yàn)楸荒ㄆ降臉邮剑愕迷僦匦略O(shè)置回來,比如input的padding等)。這就如西漢一代名將韓信哪,是成也蕭何,敗也蕭何!
2007年,Eric Meyer的一篇文章Reset Styles, 重新喚起了一股reset熱潮。下面是Eric Meyer的一個CSS Reset方案:
1. html, body, div, span, applet, object, iframe,
2. h1, h2, h3, h4, h5, h6, p, blockquote, pre,
3. a, abbr, acronym, address, big, cite, code,
4. del, dfn, em, font, img, ins, kbd, q, s, samp,
5. small, strike, strong, sub, sup, tt, var,
6. b, u, i, center,
7. dl, dt, dd, ol, ul, li,
8. fieldset, form, label, legend,
9. table, caption, tbody, tfoot, thead, tr, th, td {
10. margin: 0;
11. padding: 0;
12. border: 0;
13. outline: 0;
14. font-size: 100%;
15. vertical-align: baseline;
16. background: transparent;
17. }
AOP(Aspect-Oriented Programming,面向切面編程),可以說是OOP(面向?qū)ο缶幊蹋┑难a(bǔ)充和完善。OOP引入封裝、繼承和多態(tài)性等概念來建立一種對象層次結(jié)構(gòu),用以模擬公共行為的一個集合。當(dāng)我們需要為分散的對象引入公共行為的時候,OOP則顯得無能為力。也就是說,OOP允許你定義從上到下的關(guān)系,但并不適合定義從左到右的關(guān)系。例如日志功能。日志代碼往往水平地散布在所有對象層次中,而與它所散布到的對象的核心功能毫無關(guān)系。對于其他類型的代碼,如安全性、異常處理和透明的持續(xù)性也是如此。這種散布在各處的無關(guān)的代碼被稱為橫切(cross-cutting)代碼,在OOP設(shè)計(jì)中,它導(dǎo)致了大量代碼的重復(fù),而不利于各個模塊的重用。
而AOP技術(shù)則恰恰相反,它利用一種稱為“橫切”的技術(shù),剖解開封裝的對象內(nèi)部,并將那些影響了多個類的公共行為封裝到一個可重用模塊,并將其名為“Aspect”,即方面。所謂“方面”,簡單地說,就是將那些與業(yè)務(wù)無關(guān),卻為業(yè)務(wù)模塊所共同調(diào)用的邏輯或責(zé)任封裝起來,便于減少系統(tǒng)的重復(fù)代碼,降低模塊間的耦合度,并有利于未來的可操作性和可維護(hù)性。AOP代表的是一個橫向的關(guān)系,如果說“對象”是一個空心的圓柱體,其中封裝的是對象的屬性和行為;那么面向方面編程的方法,就仿佛一把利刃,將這些空心圓柱體剖開,以獲得其內(nèi)部的消息。而剖開的切面,也就是所謂的“方面”了。然后它又以巧奪天功的妙手將這些剖開的切面復(fù)原,不留痕跡。
Spring支持四種攔截類型:目標(biāo)方法調(diào)用前(before),目標(biāo)方法調(diào)用后(after),目標(biāo)方法調(diào)用前后(around),以及目標(biāo)方法拋出異常(throw)。
前置攔截的類必須實(shí)現(xiàn)MethodBeforeAdvice接口,實(shí)現(xiàn)其中的before方法。
后置攔截的類必須實(shí)現(xiàn)AfterReturningAdvice接口,實(shí)現(xiàn)其中的afterReturning方法。
環(huán)繞攔截的類必須實(shí)現(xiàn)MethodInterceptor接口,實(shí)現(xiàn)其中的invoke方法。環(huán)繞攔截是唯一可以控制目標(biāo)方法是否被真正調(diào)用的攔截類型,也可以控制返回對象。而前置攔截或后置攔截不能控制,它們不能印象目標(biāo)方法的調(diào)用和返回。
但是以上的攔截的問題在于,不能對于特定方法進(jìn)行攔截,而只能對某個類的全部方法作攔截。所以下面引入了兩個新概念:“切入點(diǎn)”和“引入通知”。
”切入點(diǎn)“的定義相當(dāng)于更加細(xì)化地規(guī)定了哪些方法被哪些攔截器所攔截,而并非所有的方法都被所有的攔截器所攔截。在ProxyFactoryBean的屬性中,interceptorNames屬性的對象也由攔截(Advice)變成了引入通知(Advisor),正是在Advisor中詳細(xì)定義了切入點(diǎn)(PointCut)和攔截(Advice)的對應(yīng)關(guān)系,比如常見的基于名字的切入點(diǎn)匹配(NameMatchMethodPointcutAdvisor類)和基于正則表達(dá)式的切入點(diǎn)匹配(RegExpPointcutAdvisor類)。這些切入點(diǎn)都屬于”靜態(tài)切入點(diǎn)“,因?yàn)樗麄冎辉诖韯?chuàng)建的時候被創(chuàng)建一次,而不是每次運(yùn)行都創(chuàng)建。
下面是spring的配置文件 當(dāng)然aop的配置方式有許多種,這只是其中一種
<bean id="oaTaskInstanceService4Log" parent="transactionProxy">
<property name="target">
<bean
class="com.oa.task.service.impl.OaTaskInstanceServiceImpl">
<property name="oaTaskInstanceDao">
<ref local="oaTaskInstanceDao"/>
</property>
</bean>
</property>
</bean>
<!-- instance日志所需DAO -->
<bean id="oaTaskInstanceLogDao" class="com.oa.task.dao.OaTaskInstanceLogDao">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- instance日志所需Service 此接口為 日志的業(yè)務(wù)操作接口-->
<bean id="oaTaskInstanceLogService" parent="transactionProxy">
<property name="target">
<bean
class="com.oa.task.service.impl.OaTaskInstanceLogServiceImpl">
<property name="oaTaskInstanceLogDao">
<ref local="oaTaskInstanceLogDao"/>
</property>
<property name="sysOperDao">
<ref bean="sysOperDao" />
</property>
<property name="ibatisBase">
<ref bean="ibatisBase" />
</property>
</bean>
</property>
</bean>
<!-- instance日志AOP攔截類 -->
<bean id="oaTaskInstanceLogOper" class="com.oa.task.log.OaTaskInstanceLogOper">
<property name="oaTaskInstanceLogService">
<ref local="oaTaskInstanceLogService" />
</property>
<property name="oaTaskInstanceService">
<ref local="oaTaskInstanceService4Log" />
</property>
</bean>
<!-- instance日志AOP配置綁定 -->
<bean id="oaTaskInstanceLogAutoProxy"
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<value>oaTaskInstanceService</value> //攔截的業(yè)務(wù)接口 oaTaskInstanceService內(nèi)所有方法都進(jìn)行攔截
</list>
</property>
<property name="interceptorNames">
<list>
<value>oaTaskInstanceLogOper</value> //攔截器
</list>
</property>
</bean>
/**
* 當(dāng)更新動作發(fā)生時的記錄
*/
public Object invoke(MethodInvocation invocation) throws Throwable {
String method = invocation.getMethod().getName();
Object result = null;
if(MODIFY_INSTANCE.equals(method)){//修改日志(業(yè)務(wù)邏輯 判斷方法)
......//業(yè)務(wù)操作,進(jìn)行日志的記錄
result=invocation.proceed();
}else {//不做任何日志
result=invocation.proceed();//調(diào)用原來的方法
}
return result;
}
}