spring aop(面向切面程式設計)
aop分為兩種,一種是靜態代理(不常用),另一種是動態代理 。
靜態代理的優點,及缺點:
優點:代理是客戶端不需要知道實現類是什麼,怎麼做的,客戶只需要知道代理就可以了。缺點:代理類和委託類都實現了相同的介面,代理類通過委託類實現了相同的方法,這樣就出現了大量的程式碼重複,如果介面增加一個方法除了所有實現類需要實現這個方法外,所有代理類也需要實現次方法,大大增加了程式碼維護的複雜性。代理物件只服務與一種型別的物件,如果要服務多型別的物件勢必要為每一種物件都進行代理,靜態代理在程式規模稍大時就無法勝任了
動態代理的優點 :動態代理與靜態代理相比較,最大的好處是介面中宣告的所有方法都被轉移到呼叫處理器一個集中的方法中處理,這樣,在介面方法數量比較多的時候,我們可以進行靈活處理,而不需要像靜態代理那樣每一個方法進行中轉,而且動態代理的應用使我們的類職責更加的單一,複用性更強
aop的作用:日誌記錄,效能統計,安全控制,事務處理,異常處理等等。
靜態實列:
抽象角色 IStar.java 介面(相當於明星)
public interface IStar {
public void sing();
真實角色: Zhangjie .java 繼承IStar介面的方法(相當於張傑自己)
public class Zhangjie implements IStar { @Override public void sing() { System.out.println("勿忘心安"); }
public class Zhangbingbing implements IStar {
@Override
public void sing() {
System.out.println("Sorry,對不起");
}
代理角色:XieNa.java繼承IStar介面的方法(相當於明星經紀人)
public class XieNa implements IStar { private IStar ls; public XieNa(IStar ls) { super(); this.ls = ls; } @Override public void sing() { ls.sing(); } }
測試類:
public class Temp {
public static void main(String[] args) {
IStar zj = new Zhangjie();
XieNa xn = new XieNa(zj);
xn.sing();
IStar zb = new Zhangbingbing();
XieNa xn1 = new XieNa(zb);
xn1.sing();
}
動態實列:
Person介面類 -- 抽象角色
public interface Person {
public void sleep();
}
XiaoMin .java --真實角色
public class XiaoMin implements Person {
@Override
public void sleep() {
System.out.println("睡");
}
}
DaiLi .java --代理角色
public class DaiLi implements InvocationHandler {
private Person lp;
public DaiLi(Person lp) {
super();
this.lp = lp;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(lp, args);
}
測試類:
public class Temp1 {
public static void main(String[] args) {
Person p = new XiaoMin();
DaiLi daiLi = new DaiLi(p);
Person person = (Person) Proxy.newProxyInstance(XiaoMin.class.getClassLoader(), XiaoMin.class.getInterfaces(),
daiLi);
person.sleep();
}
接下來是spring通知(動態代理)
IPerson 介面
public interface IPerson {
public void eat();
public void add();
}
繼承介面 IXiaoMing .java
public class IXiaoMing implements IPerson {
@Override
public void eat() {
System.out.println("吃");
}
@Override
public void add() {
System.out.println("add");
}
}
BeforeAdivce (前置通知)
public class BeforeAdivce implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("前置通知");
}
AfterAdivce (後置通知)
public class AfterAdivce implements AfterReturningAdvice {
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("後置通知");
}
}
InterAdivce 環繞通知
public class InterAdivce implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("返回通知");
return invocation.proceed();
}
}
applicationContext.xml
<?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"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd">
<!-- 配置混合代理物件 -->
<bean id="xm" class="com.zking.proxp2.IXiaoMing"></bean>
<!-- 配置通知 -->
<!-- 前置通知 -->
<bean id="BeforeAdvice" class="com.zking.proxp2.BeforeAdivce"></bean>
<!-- 後置通知 -->
<bean id="AfterAdivce" class="com.zking.proxp2.AfterAdivce"></bean>
<!-- 返回通知 -->
<bean id="InterAdivce" class="com.zking.proxp2.InterAdivce"></bean>
<!--配置通知的過濾 -->
<bean id="myBefore"
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<!-- 引用前置通知 -->
<property name="advice" ref="BeforeAdvice"></property>
<!-- 在方法呼叫的時候使用前置通知 -->
<!-- 以.*開頭.*結尾 中間寫的是 方法名包含的內容 -->
<property name="pattern" value=".*add.*"></property>
</bean>
<!-- 配置一個混合代理物件 -->
<bean id="myproxy"
class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 引入目標 -->
<property name="target" ref="xm"></property>
<!-- 代理類的介面 -->
<property name="proxyInterfaces">
<list>
<value>com.zking.proxp2.IPerson</value>
</list>
</property>
<property name="interceptorNames">
<list>
<idref bean="BeforeAdvice" />
<idref bean="AfterAdivce" />
<idref bean="InterAdivce" />
</list>
</property>
</bean>
</beans>
測試類
public class Temp2 {
@Test
public void Temp() {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
IPerson lp = (IPerson) ac.getBean("myproxy");
lp.add();
lp.eat();
}
}