探秘Spring AOP(上) http://debuggg.com/article/258
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就是被代理的,就可以实现内部方法调用了
更多内容请访问:IT源点
注意:本文归作者所有,未经作者允许,不得转载