普通静态代理
代理类和真实类都需要实现同一个接口
接口
package com.fchan.layui.represent.service;
/**
* 静态代理demo
*/
public interface Subject {
public void print();
}
真实类
package com.fchan.layui.represent.service.impl;
import com.fchan.layui.represent.service.Subject;
public class RealSubject implements Subject {
@Override
public void print() {
System.out.println("被代理的对象(即真实对象)的print方法");
}
}
代理类
package com.fchan.layui.represent.service.impl;
import com.fchan.layui.represent.service.Subject;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class Proxy implements Subject {
private RealSubject realSubject;
public Proxy(RealSubject realSubject) {
this.realSubject = realSubject;
}
@Override
public void print() {
log.info("代理对象开始干活了");
//被代理的对象处理业务
realSubject.print();
log.info("代理对象干活结束");
}
}
使用demo
/**
* 静态代理demo
*/
@Test
public void testRepresent(){
Subject subject = new Proxy(new RealSubject());
subject.print();
}
普通的静态代理有很大的局限性,如果需要代理的目标类实现的接口方法很多.并且这些方法都需要进行扩展的话,需要写很多.所以JDK动态代理就可以很好的解决这个问题,只需要写一个具体增强实现的类实现InvocationHandler接口.就可以在invoke方法里处理被代理对象实现的所有接口方法.
JDK动态代理
代理目标类实现的接口,因为JDK动态代理是基于接口的,接口没有的方法是代理不到的.
package com.fchan.layui.represent.service;
/**
* 接口,代理目标类实现了这个接口
*/
public interface Subject {
public void print();
}
被代理的目标类实现了这个接口
package com.fchan.layui.represent.service.impl;
import com.fchan.layui.represent.service.Subject;
public class RealSubject implements Subject {
@Override
public void print() {
System.out.println("被代理的对象(即真实对象)的print方法");
}
}
具体去增强实现的辅助类,到这里还没去使用JDK的动态代理,这里这个增强辅助类和这个代理目标类还没有啥关系
package com.fchan.layui.represent.service;
import com.fchan.layui.represent.service.impl.RealSubject;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* JDK的动态代理,利用InvocationHandler生成代理类
*/
@Slf4j
public class JdkProxySubject implements InvocationHandler {
private RealSubject realSubject;
public JdkProxySubject(RealSubject realSubject) {
this.realSubject = realSubject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log.info("开始执行动态代理的逻辑,类似spring aop的@Before通知");
Object result = null;
try {
//利用反射调用目标对象的方法
result = method.invoke(realSubject,args);
} catch (IllegalAccessException e) {
//代理类不是真正处理的类,这里接着把异常往外面抛
e.printStackTrace();
throw e;
} catch (IllegalArgumentException e) {
e.printStackTrace();
throw e;
} catch (InvocationTargetException e) {
e.printStackTrace();
throw e;
} finally {
log.info("执行finally代码块,相当于springaop的@After通知");
}
return result;
}
}
/**
* JDK的动态代理
* 需要通过接口来实现,即目标类需要实现一个业务接口
* loader:一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
*
* interfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口
* ,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
*
* h:一个InvocationHandler接口,表示代理实例的调用处理程序实现的接口。每个代理实例都具有一个关联的调用处理程序。
* 对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法(传入InvocationHandler接口的子类)
*/
@Test
public void testJDKDynamicProxy(){
RealSubject realSubject = new RealSubject();
realSubject.getClass().getInterfaces();
Subject subject = (Subject) java.lang.reflect.Proxy.newProxyInstance(this.getClass().getClassLoader()
,new Class[]{Subject.class},new JdkProxySubject(new RealSubject()));
//其实这里的JdkProxySubject就是实现了InvocationHandler接口的一个类,也可以直接通过匿名类的形式创建
/**Subject subject = (Subject) java.lang.reflect.Proxy.newProxyInstance(this.getClass().getClassLoader()
,new Class[]{Subject.class},new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return null;
}
});*/
subject.print();
}
那么JDK究竟帮我们生成了一个怎么样的代理类呢,我们可以在获取代理对象之前也就是Proxy.newProxyInstance
之前加一行参数
//将生成的字节码保存下来
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
Cglib动态代理,类似于jdk代理也要实现一个接口—MethodInterceptor接口
看了上面的2种代理方式后,实现cglib代理
就轻车熟路啦
先创建一个代理类,实现MethodInterceptor
接口
package com.fchan.layui.represent.service;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibDemoInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("cglib represent before");
Object result = null;
try {
result = methodProxy.invokeSuper(o,objects);
} catch (Throwable throwable) {
throwable.printStackTrace();
throw throwable;
} finally {
System.out.println("cglib represent finally");
}
return result;
}
}
然后用代理类去继承代理目标类
@Test
public void testCglibProxy(){
Enhancer enhancer = new Enhancer();
//设置父类也就是需要代理增强的业务类
enhancer.setSuperclass(RealSubject.class);
//具体的实现了MethodInterceptor接口的子类,也就是增强目标类的代理类
enhancer.setCallback(new CglibDemoInterceptor());
Subject subject = (Subject) enhancer.create();
subject.print();
}
代理成功~
现在我们知道有JDK动态代理和Cglib动态代理了,那么这两者有啥区别呢
JDK动态代理
只能代理实现了接口的类,并且只能代理接口拥有的方法Cglib动态代理
不能代理父类中private
和final
的方法,因为声明了这两个关键字的这些方法对于子类是不可见的.当然对于声明了final
和static
的类也是无法代理的,因为不能被继承
.
SpringAop对JDK代理和Cglib代理的选择
- 如果目标对象实现了接口,则默认采用JDK动态代理
- 如果目标对象没有实现接口,则采用Cglib进行动态代理
- 如果目标对象实现了接口,且强制cglib代理,则使用cglib代理
SpringAop实现代理类的流程
强制进行Cglib
代理
责任链模式调用demo
声明抽象类
package com.fchan.layui.chainsMethods;
public abstract class Handler {
private Handler successor;
public Handler getSuccessor() {
return successor;
}
public void setSuccessor(Handler successor) {
this.successor = successor;
}
public void handlerProcess(){
execution();
if(null != successor){
successor.handlerProcess();
}
}
public abstract void execution();
}
责任链实现demo
package com.fchan.layui.chainsMethods;
public class Client {
static class HandlerA extends Handler{
@Override
public void execution() {
System.out.println("HandlerA");
}
}
static class HandlerB extends Handler{
@Override
public void execution() {
System.out.println("HandlerB");
}
}
static class HandlerC extends Handler{
@Override
public void execution() {
System.out.println("HandlerC");
}
}
public static void main(String[] args) {
Handler handlerA = new HandlerA();
Handler handlerB = new HandlerB();
Handler handlerC = new HandlerC();
handlerA.setSuccessor(handlerB);
handlerB.setSuccessor(handlerC);
handlerA.handlerProcess();
}
}
SpringAop中责任链的实现
实际处理的方法
package com.fchan.layui.chainsMethods.springaopChain;
public abstract class ChainHandler {
public void execution(Chain chain){
handlerProcess();
chain.proceed();
}
protected abstract void handlerProcess();
}
责任链维护类
package com.fchan.layui.chainsMethods.springaopChain;
import java.util.List;
public class Chain {
List<ChainHandler> chainHandlers;
private int index = 0;
public Chain(List<ChainHandler> chainHandlers) {
this.chainHandlers = chainHandlers;
}
public List<ChainHandler> getChainHandlers() {
return chainHandlers;
}
public void setChainHandlers(List<ChainHandler> chainHandlers) {
this.chainHandlers = chainHandlers;
}
protected void proceed(){
if(index >= this.getChainHandlers().size()){
return;
}
this.getChainHandlers().get(index ++ ).execution(this);
}
}
调用实现,维护责任链顺序的客户端
package com.fchan.layui.chainsMethods.springaopChain;
import java.util.Arrays;
import java.util.List;
public class ChainClient {
static class ChainHandlerA extends ChainHandler{
@Override
protected void handlerProcess() {
System.out.println("chain handlerA");
}
}
static class ChainHandlerB extends ChainHandler{
@Override
protected void handlerProcess() {
System.out.println("chain handlerB");
}
}
static class ChainHandlerC extends ChainHandler{
@Override
protected void handlerProcess() {
System.out.println("chain handlerC");
}
}
public static void main(String[] args) {
List<ChainHandler> list = Arrays.asList(
new ChainHandlerA(),
new ChainHandlerB(),
new ChainHandlerC()
);
Chain chain = new Chain(list);
chain.proceed();
}
}
spring aop的责任链调用也是如此
类名ReflectiveMethodInvocation