JDK与Cglib代理对比

  • JDK只能针对右接口的类的接口方法进行动态代理
  • Cglib基于继承来实现代理,无法对static、final类进行代理
  • Cglib基于集成来实现代理,无法对private,static方法进行代理

Spring如何创建代理bean

  • AbstractAutoProxyCreator
  • wrapIfNecessary
  • createProxy
  • getProxy
  • ProxyFactory
  • createAopProxy
  • ProxyCreatorSupport
  • createAopProxy
  • DefaultAopProxyFactory

以下是DefaultAopProxyFactory的jdk源代码

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
public DefaultAopProxyFactory() {
}

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
return new JdkDynamicAopProxy(config);
} else {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: Either an interface or a target is required for proxy creation.");
} else {
return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
}
}
}

可以看出:里面经过判断,有两种生成代理对象的方式:其实也就是JDK和Cglib

  • new JdkDynamicAopProxy(config))
  • new ObjenesisCglibAopProxy(config)

总结:

  • 如果目标对象实现了接口,则默认采用JDK动态代理
  • 如果目标对象没有实现接口,则采用Cglib进行动态代理
  • 如果目标对象实现了几口,且强制cglib代理,则使用cglib代理

@SpringBootApplication
//强制使用cglib代理
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AopDemoApplication {
public static void main(String[] args){
SpringApplication.run(AopDemoApplicaiton.class,args)
}
}

AOP如何链式调用

责任链设计模式:

什么是责任链模式?

责任链模式就是采用一个抽象类,该类有一个自己类的对象(此对象用于存储链式的下一个节点),这样,就可以在调用该类功能之后,再拿到下一个类的引用,并调用下一个类的方法(类似于递归)

简单的实现方式(有冗余代码,类之间有关联关系,不推荐):

一个Handler(抽象类),一个Client(客户端类)

Handler.java

public abstract class Handler {
private Handler succesor;

public Handler getSuccesor() {
return succesor;
}

public void setSuccesor(Handler succesor) {
this.succesor = succesor;
}

public void execute(){
handleProcess();
if(succesor != null){
succesor.execute();
}
}

protected abstract void handleProcess();
}

Client.java

public class Client {
static class HandlerA extends Handler {
@Override
protected void handleProcess() {
System.out.println("handler by a");
}
}

static class HandlerB extends Handler{
@Override
protected void handleProcess() {
System.out.println("handler by b");
}
}

static class HandlerC extends Handler{
@Override
protected void handleProcess() {
System.out.println("handler by c");
}
}

public static void main(String[] args) {
HandlerA handlerA = new HandlerA();
HandlerB handlerB = new HandlerB();
HandlerC handlerC = new HandlerC();

handlerA.setSuccesor(handlerB);
handlerB.setSuccesor(handlerC);

handlerA.execute();
}

}

解耦的方式

通过一个List来存储对象集合,然后使用游标的形式(下标++)来完成遍历

ChainHandler.java

public abstract class ChainHandler {
public void execute(Chain chain){
handleProcess();
chain.proceed();
}

abstract void handleProcess();
}

Chain.java

public class Chain {
private List<ChainHandler> list;

public Chain(List<ChainHandler> list) {
this.list = list;
}

int index = 0;

public void proceed(){
if(index >= list.size()){
return;
}
this.list.get(index++).execute(this);
}
}

ChainClient.java

public class ChainClient {
static class ChainHandlerA extends ChainHandler{
@Override
void handleProcess() {
System.out.println("chainhandler by chain a");
}
}
static class ChainHandlerB extends ChainHandler{
@Override
void handleProcess() {
System.out.println("chainhandler by chain b");
}
}
static class ChainHandlerC extends ChainHandler{
@Override
void handleProcess() {
System.out.println("chainhandler by chain c");
}
}

public static void main(String[] args) {
new Chain(Arrays.asList(
new ChainHandlerA(),
new ChainHandlerB(),
new ChainHandlerC()
)).proceed();
}
}

Around环绕方式的参数:ProceedingJoinPoint的几个方法介绍

proceed():执行方法

getSignature():获取声明信息

Signature类如下:

public interface Signature {
String toString();

String toShortString();

String toLongString();
//方法名
String getName();
//权限修饰符
int getModifiers();
//返回值类型
Class getDeclaringType();

String getDeclaringTypeName();
}

getArgs():获取目标方法的参数列表

getTarget():返回被织入增强处理的目标对象

getThis():返回AOP框架为目标对象生成的代理对象

总结

要点清单

  • AOP适用范围及优势
  • AOP的概念及Spring切面表达式
  • AOP的实现原理及运用

使用SpringAOP的注意事项/坑

  • 不宜把重要的业务逻辑放到aop中处理
  • 无法拦截static、final、private方法
  • 无法拦截内部方法调用,因为内部调用时this.invoke(),
  • 解决方案:内部调用的时候,就不要使用this,可以从ioc容器里面去拿Bean,那个bean就是被代理的,就可以实现内部方法调用了