AOP原理
AOP:面向切面编程的原理是代理模式。
代理模式
一、静态代理
接口
1
2
3public interface Subject {
public void request();
}实现
1
2
3
4
5
6public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("realSubject execute request");
}
}代理类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20public class SubjectProxy implements Subject {
public SubjectProxy(RealSubject realSubject) {
this.realSubject = realSubject;
}
private RealSubject realSubject;
@Override
public void request() {
System.out.println("before");
try{
realSubject.request();
System.out.println("afterReturning");
}catch (Exception e){
System.out.println("AfterThrowing");;
System.out.println("ex:"+e.getMessage());
throw e;
}finally{
System.out.println("after");
}
}
}调用
1
2
3
4
5
6
7public class Client {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
SubjectProxy subjectProxy = new SubjectProxy(realSubject);
subjectProxy.request();
}
}
二、 动态代理
jdk 动态代理
1
2
3类:java.lang.reflect.Proxy
接口:InvocationHandler
只能基于接口进行动态代理编写动态代理类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23public class JdkProxySubject implements InvocationHandler {
public JdkProxySubject(RealSubject realSubject) {
this.realSubject = realSubject;
}
private RealSubject realSubject;
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before");
Object result = null;
try{
result= method.invoke(realSubject,args);
}catch(Exception e){
System.out.println("AfterThrowing");
System.out.println("ex:"+e.getMessage());
throw e;
}finally{
System.out.println("after");
}
return result;
}
}调用
1
2
3
4
5
6public class Client {
public static void main(String[] args) {
Subject subject = (Subject) Proxy.newProxyInstance(Client.class.getClassLoader(), new Class[]{Subject.class}, new JdkProxySubject(new RealSubject()));
subject.request();
}
}
cglib 动态代理
1
2
3
4
5
6
7
8
9public static getProxy(Class clazz,MethodInterceptor interceptor){
Enhancer enhancer = new Enhancer();
//生成指定类的子类,重写子类中的业务逻辑
enhancer.setSuperclass(clazz);
//通过方法反射调用目标方法
enhancer.setCallback(interceptor);
//创建子类对象
enhancer.create();
}创建要织入代码的类,实现MethodInterceptor接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16public class DemoMethodIntereptor implements MethodInterceptor {
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("before");
Object result = null;
try {
result = methodProxy.invokeSuper(obj, args);
} catch (Exception e) {
System.out.println("afterThrowing");
System.out.println("ex:" + e.getMessage());
} finally {
System.out.println("after");
}
return result;
}
}调用端
1
2
3
4
5
6
7
8
9public class Client {
public static void main(String[] args) {
Enhancer enhancer =new Enhancer();
enhancer.setSuperclass(RealSubject.class);
enhancer.setCallback(new DemoMethodIntereptor());
Subject subject = (Subject) enhancer.create();
subject.request();
}
}
jdk和cglib对比
- jdk只能动态代理有接口的类
- cglib基于继承方式实现代理,无法对static,private ,final类,方法代理。
- spring 如何选择使用jdk,cglib进行代理类
- 如果目标对象实现了接口,则默认走jdk动态代理
- 如果目标对象没有实现接口,则采用Cglib进行动态代理
- 如果目标对象实现了接口,且强制Cglib代理,则使用Cglib代理。
1
2
3
4
5
6
7
8
//强制使用cglib代理
true) (proxyTargetClass=
public static void Application(){
public static void main(String[]args){
SpringApplication.run(Application.class,args);
}
}