自己实现一个spring-AOP思路
aop的加载顺序要在IOC加载的前面,即是要实例完代理类之后才在这个实例上注入属性。
实现一个基于注解的aop:
1、定义一个切面注解 Aspect
/**
* 切面注解
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Aspect {
Class<? extends Annotation> value();
}
2、定义一个代理接口Proxy,定义一个实现这个接口的抽象类(切面代理 AspectProxy)
/**
* 代理接口
*/
public interface Proxy {
/**
* 执行链式代理
* @param proxyChain
* @return
* @throws Throwable
*/
Object doProxy(ProxyChain proxyChain) throws Throwable;
}
/**
* 切面代理
*/
public abstract class AspectProxy implements Proxy {
private static final Logger logger = LoggerFactory.getLogger(AspectProxy.class);
@Override
public final Object doProxy(ProxyChain proxyChain) throws Throwable {
Object result = null;
Class<?> cls = proxyChain.getTargetClass();
Method method = proxyChain.getTargetMethod();
Object[] params = proxyChain.getMethodParams();
begin();
try {
if (intercept(cls, method, params)) {
boolean flag = before(cls, method, params);
if(!flag){
return "...";
}
result = proxyChain.doProxyChain();
after(cls, method, params, result);
} else {
result = proxyChain.doProxyChain();
}
} catch (Exception e) {
logger.error("proxy failure", e);
error(cls, method, params, e);
throw e;
} finally {
end();
}
return result;
}
public void begin() {
}
public boolean intercept(Class<?> cls, Method method, Object[] params) throws Throwable {
return true;
}
public boolean before(Class<?> cls, Method method, Object[] params) throws Throwable {
return true;
}
public boolean after(Class<?> cls, Method method, Object[] params, Object result) throws Throwable {
return true;
}
public void error(Class<?> cls, Method method, Object[] params, Throwable e) {
}
public void end() {
}
}
3、定义一个代理链ProxyChain
/**
* 代理链
*
*/
public class ProxyChain {
private final Class<?> targetClass;//目标类
private final Object targetObject;//目标对象
private final Method targetMethod;//目标方法
private final MethodProxy methodProxy;//方法代理
private final Object[] methodParams;//方法参数
private List<Proxy> proxyList = new ArrayList<Proxy>();//代理列表
private int proxyIndex = 0;//代理索引
public ProxyChain(Class<?> targetClass, Object targetObject, Method targetMethod, MethodProxy methodProxy, Object[] methodParams, List<Proxy> proxyList) {
this.targetClass = targetClass;
this.targetObject = targetObject;
this.targetMethod = targetMethod;
this.methodProxy = methodProxy;
this.methodParams = methodParams;
this.proxyList = proxyList;
}
public Object[] getMethodParams() {
return methodParams;
}
public Class<?> getTargetClass() {
return targetClass;
}
public Method getTargetMethod() {
return targetMethod;
}
public Object doProxyChain() throws Throwable {
Object methodResult;
if (proxyIndex < proxyList.size()) {//如果链还没调用完
methodResult = proxyList.get(proxyIndex++).doProxy(this);//调用切面代理类,切面代理类会回调
} else {//调用完成,执行目标对象的业务逻辑
methodResult = methodProxy.invokeSuper(targetObject, methodParams);
}
return methodResult;
}
}
4、定义一个代理管理器 ProxyManager,该类会在项目启动的时候就被调用,用来实例化目标类
* 代理管理器
*
*/
public class ProxyManager {
@SuppressWarnings("unchecked")
public static <T> T createProxy(final Class<?> targetClass, final List<Proxy> proxyList) {
return (T) Enhancer.create(targetClass, new MethodInterceptor() {
@Override
public Object intercept(Object targetObject, Method targetMethod, Object[] methodParams, MethodProxy methodProxy) throws Throwable {
return new ProxyChain(targetClass, targetObject, targetMethod, methodProxy, methodParams, proxyList).doProxyChain();//生成完整的代理链职责实例
}
});
}
}
5、AOPHelper,负责项目启动时,获取需要生成代理的类,调用ProxyManager,实例化好这些类后保存实例在beans中,后续访问调用将拥有aop功能。
static {
try {
Map<Class<?>, Set<Class<?>>> proxyMap = createProxyMap();//获取AspectProxy的子类,如果子类有Aspect注解,获取注解中的值,这个值也是个注解类,根据这个注解类去获取所有含有这个注解类的类(这个是基于注解的aop的关键)
Map<Class<?>, List<Proxy>> targetMap = createTargetMap(proxyMap);//根据上一步组装将要被代理的目标类的代理链
for (Map.Entry<Class<?>, List<Proxy>> targetEntry : targetMap.entrySet()) {//变量每个需要被代理的类
Class<?> targetClass = targetEntry.getKey();
List<Proxy> proxyList = targetEntry.getValue();
System.out.println("targetClass:"+targetClass.getName());
System.out.println("proxyList:"+proxyList.get(0).toString());
Object proxy = ProxyManager.createProxy(targetClass, proxyList);//实例化
BeanHelper.setBean(targetClass, proxy);//将实例化好的代理类保存到Beans中
}
} catch (Exception e) {
LOGGER.error("aop failure", e);
}
}
------------------------------------------------------至此,一个简单的aop开发完成-----------------------------------------
调用:
/**
* 拦截 Controller 所有方法,这里可以做权限控制,日志记录,性能监控等等
*/
@Aspect(Controller.class)
public class ControllerAspect extends AspectProxy {
private static final Logger LOGGER = LoggerFactory.getLogger(ControllerAspect.class);
private long begin;
@Override
public boolean before(Class<?> cls, Method method, Object[] params) throws Throwable {
LOGGER.debug("---------- begin ControllerAspect ----------");
if(true){
return true;
}
return false;
}
@Override
public boolean after(Class<?> cls, Method method, Object[] params, Object result) throws Throwable {
LOGGER.debug("----------- end ControllerAspect-----------");
if(true){
return true;
}
return false;
}
}