Aop是面向切片的编程,首先先用图解释AOP的编程
这是没有用aop的情况,代码中存在大量的重复的代码:
使用aop就是采用一个切片,对封装好的程序进行切开,减少重复的代码,对重复的代码进行复用:
那么如何实现这种aop的切片编程了?就是使用动态代理的方式,为方法增加方法,现在就讲一讲代理的原理:
代理就相当于处于一个中间层,当一个对象不能调用另一个对象的方法时候,可以通过代理进行调用。
首先是静态代理:
静态代理相当于首先定义了一个接口,接口中有个方法,出于不同的需要,我们有很多子类实现了这个接口并重写了这个接口中的方法(被代理类)。静态代理处于中间层不断调用代理类。
下面给出实现代理的源代码:
1.接口的实现
/** * Subject接口的实现 */ public interface Subject { void visit(); }
2.产生被代理类
/** * Subject接口的实现 */ public class SubjectImpl implements Subject { public void visit() { System.out.println("SubjectImpl!"); } }
3.中间层代理类
public class ProxySubject implements Subject { private Subject subject; public ProxySubject(Subject subject) { this.subject = subject; } public void visit() { subject.visit(); } }
4.使用代理类
public class Client { public static void main(String[] args) { ProxySubject subject=new ProxySubject(new SubjectImpl()); subject.visit(); } }
由此可以看到,我们对接口中的方法进行了扩充。aop中使用代理就是对方法进行扩充
现在讲一讲动态代理:
由上面的例子可以看出,你对接口中的方法进行扩充的时候,你每次都要进行新建一个类,给代理类进行调用,以后程序越写越多就会十分麻烦,那这个时候就要用到动态代理,就在产生的被代理类上进行扩充,而不需要频繁的进行建类。
下面给出动态代理的实现源代码:
1.接口类
/** * Subject接口的实现 */ public interface Subject { void visit(); }
2.被代理类
/** * Subject接口的实现 */ public class SubjectImpl implements Subject { public void visit() { System.out.println("SubjectImpl!"); } }3.使用handler对被代理类进行扩充
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class Handler implements InvocationHandler { private Object target; public Handler(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("开始事务!"); method.invoke(target,args); System.out.println("事务结束!"); return null; } }
4.调用代理类
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class Client { public static void main(String[] args) { SubjectImpl subjectImpl=new SubjectImpl(); InvocationHandler handler=new Handler(subjectImpl); Subject subject = (Subject) Proxy.newProxyInstance(subjectImpl.getClass().getClassLoader(), subjectImpl.getClass().getInterfaces(), handler); subject.visit(); } }
Proxy.newProxyInstance用于产生参数
第一个参数:ClassLoader loader:它是类加载器类型
第二个参数:Class[] interfaces:指定newProxyInstance()方法返回的对象要实现哪些接口,没错,可以指定多个接口
第三个参数:handler主要就是对方法增加内容
aop面向切片编程就是这样为方法增加内容,aop主要使用Cglin代理和动态代理,动态代理传入的是个接口,而cglib闯入是对象,Spirng自行选择该使用何种方法。总之是为了在原基础上增加内容。