AOP为Aspect Oriented Programming的缩写,意为:面向切面编程。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。这里介绍AOP的基本技术JDK动态代理和Cglib
应用场景
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();
}
}
ebIptA.jpg
需要在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();
}
}
ebIPpt.jpg
这种写死代码的方式,如果类文件多至几百个,那么就需要改几百处代码。同时,如果我们引用的是第三方jar,这个时候我们不太容易去改变第三方的jar。
方法二(静态代理)
我们不去写死原来文件代码,我们给greeting接口写一个静态代理
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();
}
}
ebIi1P.jpg
我们通过给greeting接口提供一个静态代理GreetingStaticProxy成功的解决了写死代码的问题,但是如果接口增多,比如增加一个Complain接口,那么就需要增加一个ComplainStaticProxy。最终XxxxStaticProxy类会越来越多。如何才能让这些代理类尽可能的减少?最好只有一个代理类,我们可以用JDK的动态代理。
方法三(JDK动态代理)
JDK动态代理关键类,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();
}
}
ebI9fI.jpg
及时增加了很多Greeting之外的接口,我们都可以通过DynamicProxy一个代理类来进行代理。但是这样做仍然存在一个问题,就是JDK提供的代理类只能代理接口,而不能代理没有接口的类。有什么方案可以解决这个问题么?
方法四(Cglib代理)
Cglib代理关键类,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的动态代理和Cglib来实现的。
网友评论