1.Joinpoint切点,就是方法执行的那个具体的点,抽象出一个接口:
//切点
public interface Joinpoint {
// 切点的执行点
Object proceed();
// 获取切点所在的方法
Method getMethod();
//目标类
Object getThis();
//目标类执行的参数
Object[] getArguments();
}
2.Advice通知,就是切面逻辑,抽象出一个接口
//切面逻辑,通知
public interface Advice {
}
3.Pointcut,可以理解为,Joinpoint的表述形式,例如1: get就是表示get方法处的这个Joinpoint
例如2: ge* 就表示所有ge开头的方法处,都可以作为Joinpoint.
这里没有具体给出实现方式,为了完善概念而已,默认对所有方法都匹配
public class Pointcut {
}
4.Advisor 通知器,包含了Pointcut 和Advice,抽象出一个接口
//通知器,里面含有Pointcut和Advice
public interface Advisor {
Pointcut getPointcut();
Advice getAdvice();
}
并提供一个默认的实现
public class DefaultPointcutAdvisor implements Advisor {
private Pointcut pointcut;
private Advice advice;
public DefaultPointcutAdvisor(Advice advice, Pointcut pointcut) {
this.pointcut = pointcut;
this.advice = advice;
}
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
@Override
public Advice getAdvice() {
return this.advice;
}
}
5.以jdk的动态代理来说,如果需要创建一个目标类的代理对象,并执行相应的逻辑,需要目标类,目标类所实现的接口,还有通知器Advisor,所以可以把这些封装成一个对象AdvisedSupport,表示用来创建一个目标类的代理对象所需要的原材料.
//创建代理对象的载体,如目标对象,advice,ponitcut,advisor
public class AdvisedSupport {
// 目标对象
private Object target;
// 代理对象实现的接口
private List<Class<?>> interfaces = new ArrayList<>();
private List<Advisor> advisors = new ArrayList<>();
}
6.抽象出一个工厂(或者委托)AopProxy,用来生产代理对象
//用于创建代理对象的委托
public interface AopProxy {
//获取代理对象
Object getProxy();
}
7.有了这些,我们就可以创建目标类的代理对象了,这里可以使用抽象工厂模式,抽象出大工厂AopProxyFactory,用来生产AopProxy
//生成 产生代理对象的工厂的工厂
public interface AopProxyFactory {
//根据AdvisedSupport,创建AopProxy
AopProxy createAopProxy(AdvisedSupport advisedSupport);
}
8.提供AopProxy 具体的实现类,使用jdk来创建,顺便实现InvocationHandler这个接口
//使用jdk的动态代理生成代理对象
public class JdkDynamicAopProxy implements AopProxy, InvocationHandler {
//创建代理对象所需要的原材料
private AdvisedSupport advisedSupport;
public JdkDynamicAopProxy(AdvisedSupport advisedSupport) {
this.advisedSupport = advisedSupport;
}
@Override
public Object getProxy() {
return Proxy.newProxyInstance(this.getClass().getClassLoader(), advisedSupport.getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws
//TODO这里的逻辑后续补上
}
}
9.使用抽象工厂模式,创建aop的代理对象
//生成 产生代理对象的工厂的工厂
public interface AopProxyFactory {
AopProxy createAopProxy(AdvisedSupport advisedSupport);
}
提供一个默认实现
public class DefaultAopProxyFactory implements AopProxyFactory {
@Override
public AopProxy createAopProxy(AdvisedSupport advisedSupport) {
Object target = advisedSupport.getTarget();
if (target.getClass().getInterfaces().length > 0) {
return new JdkDynamicAopProxy(advisedSupport);
}else{
//cglib
return null;
}
}
}
10.java中方法的执行,一般是一个对象调用一个方法,所以可以把方法的执行,抽象出一个接口,MethodInvocation 继承Joinpoint
public interface MethodInvocation extends Joinpoint{
}
可以补上第八步骤中TODO的部分代码
MethodInvocation invocation;
return invocation.proceed();
11,抽象出一个方法拦截器,就是通知器,所有通知的执行点,都从这个方法上走
//方法拦截,这里可以进行方法拦截
public interface MethodInterceptor extends Advice {
Object invoke(MethodInvocation invocation);
}
12.抽象出一个前置通知,MethodBeforeAdvice
//前置通知
public interface MethodBeforeAdvice extends Advice {
void before(Method method, Object[] args, Object target);
}
13.如果有一个前置通知,通知执行的是从MethodInterceptor 这个方法中的invoke方法中进入,所以需要将MethodBeforeAdvice 包装成MethodInterceptor,提供一个实现
public class MethodBeforeAdviceInterceptor implements MethodInterceptor {
private MethodBeforeAdvice advice;
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation invocation) {
advice.before(invocation.getMethod(), invocation.getArguments(), invocation.getThis());
return invocation.proceed();
}
}
14.这里需要一个能将Advice转换成MethodInterceptor的适配器AdvisorAdapter,先抽象出一个接口
//将Advice转换为MethodInterceptor
public interface AdvisorAdapter {
MethodInterceptor getInterceptor(Advisor advisor);
}
并提供一个能将MethodBeforeAdvice转换成MethodInterceptor的一个实现
public class MethodBeforeAdviceAdapter implements AdvisorAdapter {
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
return new MethodBeforeAdviceInterceptor(advice);
}
}
15,这里补全所有的AdvisedSupport的支持,
//创建代理对象的载体,如目标对象,advice,ponitcut,advisor
public class AdvisedSupport {
// 目标对象
private Object target;
// 代理对象实现的接口
private List<Class<?>> interfaces = new ArrayList<>();
private List<Advisor> advisors = new ArrayList<>();
//默认的适配器,advice适配成MethodInterceptor
private AdvisorAdapter advisorAdapter = new MethodBeforeAdviceAdapter();
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
// 添加目标对象对象所实现的接口
public void addInterface(Class<?>... interfaces) {
this.interfaces.clear();
for (Class<?> ifc : interfaces) {
this.interfaces.add(ifc);
}
}
public Class<?>[] getInterfaces() {
return interfaces.toArray(new Class<?>[0]);
}
public void setInterfaces(List<Class<?>> interfaces) {
this.interfaces = interfaces;
}
public List<Advisor> getAdvisors() {
return advisors;
}
public void setAdvisors(List<Advisor> advisors) {
this.advisors = advisors;
}
//根据advisor,获取到advice,并将advice,适配成所有的MethodInterceptor
public List<Object> getInterceptorsAndDynamicInterceptionAdvice() {
List<Object> interceptorList = new ArrayList<>();
for (Advisor advisor : this.advisors) {
if (advisor instanceof DefaultPointcutAdvisor) {
interceptorList.add(advisorAdapter.getInterceptor(advisor));
}
}
return interceptorList;
}
//如果添加的是一个advice,封装成一个Advisor,并加入链表
public void addAdvice(Advice advice) {
addAdvisor(new DefaultPointcutAdvisor(advice, null));
}
public void addAdvisor(Advisor advisor) {
this.advisors.add(advisor);
}
}
16.因为生产的代理对象之后,执行方法,都是从JdkDynamicAopProxy中invoke中的方法进入,这里我有转换成从MethodInvocation的proceed()方法进入,所以这里提供一个MethodInvocation的实现,用来处理方法的通知,和调用,
//处理切面逻辑的地方
public class ReflectiveMethodInvocation implements MethodInvocation {
// 代理对象
private Object proxy;
// 目标对象
private Object target;
// 目标方法
private Method method;
// 一连串的通知器,都封装成MethodInterceptor
protected final List<?> interceptorsAndDynamicMethodMatchers;
private Object[] aguments;
// 代表执行到第几个通知器链
private int currentInterceptorIndex = -1;
public ReflectiveMethodInvocation(Object proxy, Object target, Method method, Object[] aguments,
List<Object> interceptorsAndDynamicMethodMatchers) {
this.proxy = proxy;
this.target = target;
this.method = method;
this.aguments = aguments;
this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
}
@Override
public Object proceed() {
if (this.currentInterceptorIndex == interceptorsAndDynamicMethodMatchers.size() - 1) {
try {
//目标方法的最终调用
return method.invoke(target, aguments);
} catch (Exception e) {
e.printStackTrace();
}
}
//这里就是将advice封装成MethodInterceptor.从链表中一个一个执行
Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers
.get(++this.currentInterceptorIndex);
//这里将ReflectiveMethodInvocation自己用传入了,所以是一个递归调用
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
@Override
public Method getMethod() {
return method;
}
@Override
public Object getThis() {
return target;
}
@Override
public Object[] getArguments() {
return aguments;
}
}
17.完善第八步骤中的invoke方法,
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
// 获取到所有的调用器链
List<Object> chain = this.advisedSupport.getInterceptorsAndDynamicInterceptionAdvice();
invocation = new ReflectiveMethodInvocation(proxy, advisedSupport.getTarget(), method, args, chain);
return invocation.proceed();
}
}
到这里,spring中aop的核心实现就是这样,然后结合spring中的Factorybean,或者BeanPostProcessor.就完成spring中aop功能的实现
测试类:
public class Test01 {
public static void main(String[] args) {
IA ia = new AImpl();
ProxyFactory proxyFactory = new ProxyFactory(ia);
proxyFactory.addInterface(IA.class);
proxyFactory.addAdvice(new MethodBeforeAdvice() {
@Override
public void before(Method method, Object[] args, Object target) {
System.out.println("1-----------------");
}
});
proxyFactory.addAdvice(new MethodBeforeAdvice() {
@Override
public void before(Method method, Object[] args, Object target) {
System.out.println("2----------------");
}
});
IA proxyObj = (IA) proxyFactory.getProxy();
proxyObj.ext();
}
}
interface IA{
void ext();
}
class AImpl implements IA{
@Override
public void ext() {
System.out.println("--------------");
}
}