AOP為Aspect Oriented Programming的縮寫,意為:面向切面編程冬骚。利用AOP可以對業(yè)務(wù)邏輯的各個部分進(jìn)行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高程序的可重用性战虏,同時提高了開發(fā)的效率拣宰。這里介紹AOP的基本技術(shù)JDK動態(tài)代理和Cglib
應(yīng)用場景
public interface Greeting {
void sayHello();
}
class Programmer implements Greeting {
@Override
public void sayHello() {
System.out.println("Hello,I'm programmer");
}
}
class Student implements Greeting {
@Override
public void sayHello() {
System.out.println("Hello,I'm student");
}
}
class Teacher implements Greeting {
@Override
public void sayHello() {
System.out.println("Hello,I'm teacher");
}
}
public class Client {
public static void main(String args[]) {
Greeting greeting=new Student();
greeting.sayHello();
greeting=new Teacher();
greeting.sayHello();
greeting=new Programmer();
greeting.sayHello();
}
}
需要在sayHello方法前后,分別輸出call before,call after.
方法一(寫死代碼)
我們可以用最簡單的方式烦感,寫死代碼來完成這個功能巡社。
class Programmer implements Greeting {
@Override
public void sayHello() {
System.out.println("call before");
System.out.println("Hello,I'm programmer");
System.out.println("call after");
}
}
class Student implements Greeting {
@Override
public void sayHello() {
System.out.println("call before");
System.out.println("Hello,I'm student");
System.out.println("call after");
}
}
class Teacher implements Greeting {
@Override
public void sayHello() {
System.out.println("call before");
System.out.println("Hello,I'm teacher");
System.out.println("call after");
}
}
public class Client1 {
public static void main(String args[]) {
Greeting greeting=new Student();
greeting.sayHello();
greeting=new Teacher();
greeting.sayHello();
greeting=new Programmer();
greeting.sayHello();
}
}
這種寫死代碼的方式,如果類文件多至幾百個手趣,那么就需要改幾百處代碼晌该。同時,如果我們引用的是第三方j(luò)ar绿渣,這個時候我們不太容易去改變第三方的jar朝群。
方法二(靜態(tài)代理)
我們不去寫死原來文件代碼,我們給greeting接口寫一個靜態(tài)代理
public class GreetingStaticProxy implements Greeting {
private Greeting greeting;
public GreetingStaticProxy(Greeting greeting) {
this.greeting = greeting;
}
@Override
public void sayHello() {
before();
greeting.sayHello();
after();
}
private void after() {
System.out.println("call after");
}
private void before() {
System.out.println("call before");
}
}
public class Client2 {
public static void main(String args[]) {
Greeting studentStaticProxy=new GreetingStaticProxy(new Student());
studentStaticProxy.sayHello();
Greeting teacherStaticProxy=new GreetingStaticProxy(new Teacher());
teacherStaticProxy.sayHello();
Greeting programmerStaticProxy=new GreetingStaticProxy(new Programmer());
programmerStaticProxy.sayHello();
}
}
我們通過給greeting接口提供一個靜態(tài)代理GreetingStaticProxy成功的解決了寫死代碼的問題中符,但是如果接口增多姜胖,比如增加一個Complain接口,那么就需要增加一個ComplainStaticProxy淀散。最終XxxxStaticProxy類會越來越多右莱。如何才能讓這些代理類盡可能的減少?最好只有一個代理類档插,我們可以用JDK的動態(tài)代理隧出。
方法三(JDK動態(tài)代理)
JDK動態(tài)代理關(guān)鍵類,InvocationHandler阀捅,Proxy這兩個類胀瞪。
public class DynamicProxy {
public static <T> T createProxy(final T t) {
return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), t.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object result = method.invoke(t, args);
after();
return result;
}
private void after() {
System.out.println("call after");
}
private void before() {
System.out.println("call before");
}
});
}
}
public class Client3 {
public static void main(String args[]) {
Greeting studentDynaminProxy = DynamicProxy.createProxy(new Student());
studentDynaminProxy.sayHello();
Greeting teacherDynicProxy = DynamicProxy.createProxy(new Teacher());
teacherDynicProxy.sayHello();
Greeting programmerDynicProxy = DynamicProxy.createProxy(new Programmer());
programmerDynicProxy.sayHello();
}
}
及時增加了很多Greeting之外的接口,我們都可以通過DynamicProxy一個代理類來進(jìn)行代理饲鄙。但是這樣做仍然存在一個問題凄诞,就是JDK提供的代理類只能代理接口,而不能代理沒有接口的類忍级。有什么方案可以解決這個問題么帆谍?
方法四(Cglib代理)
Cglib代理關(guān)鍵類,MethodInterceptor,Enhancer這兩個類
public class CglibDynamicProxy {
public static <T> T createProxy(Class<T> tClass) {
return (T) Enhancer.create(tClass, new MethodInterceptor() {
public Object intercept(Object targerObject, Method method, Object[] params, MethodProxy methodProxy) throws Throwable {
before();
Object result = methodProxy.invokeSuper(targerObject, params);
after();
return result;
}
private void after() {
System.out.println("call after");
}
private void before() {
System.out.println("call before");
}
});
}
}
public class Client4 {
public static void main(String args[]) {
Student studentCglibProxy=CglibDynamicProxy.createProxy(Student.class);
studentCglibProxy.sayHello();
Teacher teacherCglibProxy=CglibDynamicProxy.createProxy(Teacher.class);
teacherCglibProxy.sayHello();
Programmer programmerCglibProxy=CglibDynamicProxy.createProxy(Programmer.class);
programmerCglibProxy.sayHello();
}
}
[圖片上傳失敗...(image-3e97d1-1565621044900)]
Spring AOP就是基于JDK的動態(tài)代理和Cglib來實現(xiàn)的轴咱。