Spring初級知識學習(2)
AOP(面向切面程式設計)用來做安全驗證,記錄日誌,效能檢驗等等。
代理模式:對進行操作的物件的物件的代理。
代理物件和被代理物件:
代理分為靜態代理和動態代理,靜態代理是指在編譯階段就能確定代理物件的被代理物件,代理類需要和被代理類一一對應。
動態代理指在執行階段確定代理物件的被代理物件(一個代理類可以確定多個被代理類)。
靜態代理的實現:
1、定義代理類,代理類應該和被代理類實現同一個介面並封裝被代理物件
2、通過代理物件去代替被代理物件完成業務
動態代理:在執行階段動態的確定代理物件和被代理物件的協議,代理類只有一個,動態代理是基於反射的基礎之上實現的。反射是指通過獲得類的Class例項,可以得到該類的內部資訊包括例項化。
正常建立學生物件是通過Student s = new Student();
s.setAge(10);
反射是這樣的:Class c = Student.class;//每個類裡面都有一個靜態的常量。class.
c.getClassLoader();//獲得載入類器
Student s1 = (Student)c.newInstance();//建立新的例項。這個newInstance呼叫的是無參構造。所以必須有無參構造。
大Class當然也可以通過類名來獲得,也可以通過物件來獲得,像上面的Class c1 = s.getClass().
Field fs[] = c.getFields();//獲得所有的屬性名字,反射的類多在java.lang.reflect包裡。.Field
for(int i = 0 ;i<fs.length;i++){
System.out.println(fs[i].getName());//只能打印出共有的屬性哈。public那種
}
Method ms[] = c.getMethods();//java.lang.reflect.Method
for(int i = 0 ;i<ms.length;i++){
System.out.println(ms[i].getName());//只能打印出共有的屬性哈。public那種
}
c.getField(String fieldname);//獲得某個欄位的值。
Class c = Student.class;
Student obj = (Student)c.newInstance();
c.getMethod("setAge",int.class).invoke(obj,new Integer[]{2});//通過Class的例項的方法getMethod();第一個引數傳方法名:setAge,字串型的呀。第二個引數傳引數型別的class.因為setAget(int aget);方法invoke的第一個引數obj是要呼叫哪個物件例項的方法 ,這個是物件的例項。第二個引數是呼叫setAge時引數的值。這裡是2.
System.out.println(obj.getAge());//顯示為2
學反射是為了學習動態代理。
動態代理第一步:定義代理類,代理類實現InvocationHandler,實現invoke方法,並封裝被代理物件,建立帶引數構造把被代理物件傳進去啊。被代理物件為Object型別。
StudentDaoImp dao = new StudentDaoImp();
StudentDaoService daoService = new StudentDaoServiceImp(dao);
//動態代理是基於介面的代理
DynamicProxy dp = new DynamicProxy(daoSerivice);
//生成代理物件
StudentDaoSerivce service = (StudentDaoService)Proxy.newProxyInstance(StudentDaoServiceImp.class.getClassLoader(),//被代理物件的類的載入器
StudentDaoServiceImp.class.getInstances(),//被代理類所實現的全部介面
dp);
service.delete(new Student());
AOP:Aspact Object Programming面向切面程式設計。切面是指用來處理安全驗證,效能測試,和記錄日誌的類。我們叫做切面。切面也是一個類。一個抽象化的叫法。屬於切面的類中有方法可以橫切業務邏輯類的方法。
AOP代理有JDK動態代理或者CGLIB代理。前者是對介面的代理,後者是對類的代理。
在ApplicationContext.xml中進行AOP的配置
<bean name="myAspect" class="com.ts.aspect.MyAspect"></bean>
<aop:config>
<aop:pointcut expression="excution(* com.ts.service.imp.Student.*(..))" id="pcMethod"/>///////////星的位置表示關注點要橫切的方法的返回值型別。*表任意型別。*後面是空格,再後面是要橫切的類的包或者類。類的*表示這個類的所有方法都要橫切。括號裡的點點表示任意個引數,如果括號裡是空的,表示呼叫無參構造,也可以指定引數的型別。注意啊。id是不能重的。給id起一個名標識唯一。
上面是連線點。下面是通知。
<aop:aspect id="aspect" ref="myAspect">///////把上面定義的切面引入進來
<aop:after method="doAfter" pointcut-ref="pcMethod"/>
<aop:before method="doBefore" pointcut-ref="pcMethod"/>///////pointcut-reft指定上面定義的pointcut的id.
</aop:aspect>
</aop:config>
spring有一個JoinPoint。把這個當做引數傳到切面的方法中,可以通過jp.getSignature().getName()得到切面方法的名字。可以通過jp.getArgs()得到切面方法的引數陣列。
如果是doAround.中間還可以傳一個ProceedingJoinPoint型別的引數。
切面型別中有如下切面方法 。
public void doAround(ProceedingJointPoint pjp){
long time1 = System.currentTimeMillis();
pjp.proceed();
long time2 = System.currentTimeMillis();
System.out.println("執行"+pjp.getSignature().getName()+"()方法共耗時"+(time2-time1)+"毫秒");
Spring是一個強大的框架,它對Struts提供也支援,也對Hibernate提供了支援。只需要提供相關的jar包就行了。
在Spring中進行事務管理器的配置。
下面定義了一個Spring的sessionFactory的Bean。
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation" value="file:src/hibernate.cfg.xml">
</property>
</bean>
<!--配置事務管理器物件-->
<bean name="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<!--注入sessionFactory物件 -->
<property name="sessionFactory" ref="sessionFactory">
</bean>
<!-- 配置納入事務管理中的方法--!>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--需要開啟事務管理的時候自動開啟---!>
<tx:method name="insert*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="*" read-only="true"/>
</tx:attributes>
</tx:advice>
<aop:config>
<!--需要事務連線點---!>
<aop:pointcut expression="execution(* com.ts.service.imp.*.*(..))" id="pcMethod"/>
<!--需要通知---!>
<aop:advice advice-ref="txAdvice" pointcut-ref="pcMethod"/>
</aop:config>