自分でspring-AOPの構想を実現します.
6466 ワード
aopのローディング順序は、IOCローディングの前、すなわちプロキシクラスのインスタンスが完了した後に、このインスタンスに属性を注入する必要がある.
注釈ベースのaopを実現します.
1、切断面を定義してAsppectを注釈する
呼び出し:
注釈ベースのaopを実現します.
1、切断面を定義してAsppectを注釈する
/**
*
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Aspect {
Class extends Annotation> value();
}
2、代理インターフェースProxyを定義し、このインターフェースを実現する抽象類を定義します. AsppectProxy)/**
*
*/
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、代理チェーンProxyChinを定義する/**
*
*
*/
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 proxyList = new ArrayList();//
private int proxyIndex = 0;//
public ProxyChain(Class> targetClass, Object targetObject, Method targetMethod, MethodProxy methodProxy, Object[] methodParams, List 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 createProxy(final Class> targetClass, final List 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、AOPAHelperは、プロジェクトの起動時に、プロキシを生成するクラスを取得し、ProxyManagerを呼び出し、これらのクラスを実際化して保存したインスタンスをbeansに保存し、その後のアクセス呼び出しはaop機能を持つ.static {
try {
Map, Set>> proxyMap = createProxyMap();// AspectProxy , Aspect , , , ( aop )
Map, List> targetMap = createTargetMap(proxyMap);//
for (Map.Entry, List> targetEntry : targetMap.entrySet()) {//
Class> targetClass = targetEntry.getKey();
List 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;
}
}