Skip to content

Commit

Permalink
添加AOP特性
Browse files Browse the repository at this point in the history
  • Loading branch information
刘义 committed Feb 17, 2019
1 parent 493e057 commit f851ea9
Show file tree
Hide file tree
Showing 10 changed files with 349 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.custom.framework.annotation;

import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* @author liuyi
* @date 2019/2/16
*/

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Aspect {
/**
* 注解
* @return
*/
Class<? extends Annotation> value();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.custom.framework.aspect;

import com.custom.framework.proxy.AspectProxy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;

/**
* @author liuyi
* @date 2019/2/17
*/
public class ControllerAspect extends AspectProxy {

private static final Logger logger = LoggerFactory.getLogger(ControllerAspect.class);

private long begin;

@Override
public void before(Class<?> cls, Method method, Object[] params) throws Throwable {
logger.debug("---------- begin ----------");
logger.debug(String.format("class: %s", cls.getName()));
logger.debug(String.format("method: %s", method.getName()));
begin = System.currentTimeMillis();
}

@Override
public void after(Class<?> cls, Method method, Object[] params) throws Throwable {
logger.debug(String.format("time: %dms", System.currentTimeMillis() - begin));
logger.debug("---------- end ----------");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,13 @@ public static <T> T getBean(Class<T> cls) {
return (T)BEAN_MAP.get(cls);
}

/**
* 设置Bean 实例
* @param cls
* @param obj
*/
public static void setBeanMap(Class<?> cls, Object obj) {
BEAN_MAP.put(cls, obj);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.custom.framework.annotation.Service;
import com.custom.framework.util.ClassUtil;

import java.lang.annotation.Annotation;
import java.util.HashSet;
import java.util.Set;

Expand Down Expand Up @@ -71,5 +72,34 @@ public static Set<Class<?>> getBeanClassSet() {
return beanClassSet;
}

/**
* 获取基础包名中指定父类或接口的相关类
*/
public static Set<Class<?>> getClassSetBySuper(Class<?> superClass) {
Set<Class<?>> classSet = new HashSet<>();
for (Class<?> cls : CLASS_SET) {
if (superClass.isAssignableFrom(cls) && !superClass.equals(cls)) {
classSet.add(cls);
}
}
return classSet;
}

/**
* 获取应用包名下带有某注解的所有类
* @param annotationClass
* @return
*/
public static Set<Class<?>> getClassSetByAnnotation(Class<? extends Annotation> annotationClass) {
Set<Class<?>> classSet = new HashSet<>();
for (Class<?> cls : CLASS_SET) {
if (cls.isAnnotationPresent(annotationClass)) {
classSet.add(cls);
}
}
return classSet;
}



}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.custom.framework.helper;

import com.custom.framework.annotation.Controller;
import com.custom.framework.proxy.AopHelper;
import com.custom.framework.util.ClassUtil;

/**
Expand All @@ -14,8 +15,9 @@ public static void init() {
Class<?>[] classList = {
ClassHelper.class,
BeanHelper.class,
AopHelper.class,
IocHelper.class,
Controller.class
Controller.class,
};
for (Class<?> cls : classList) {
ClassUtil.loadClass(cls.getName(),true);
Expand Down
93 changes: 93 additions & 0 deletions framework/src/main/java/com/custom/framework/proxy/AopHelper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package com.custom.framework.proxy;

import com.custom.framework.annotation.Aspect;
import com.custom.framework.helper.BeanHelper;
import com.custom.framework.helper.ClassHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* 初始化 AOP 框架
*
* @author huangyong
* @since 1.0
*/
public class AopHelper {
private static final Logger logger = LoggerFactory.getLogger(AopHelper.class);

static {
try {
// 创建 Proxy Map(用于 存放代理类 与 目标类列表 的映射关系)
Map<Class<?>, Set<Class<?>>> proxyMap = createProxyMap();
// 创建 Target Map(用于 存放目标类 与 代理类列表 的映射关系)
Map<Class<?>, List<Proxy>> targetMap = createTargetMap(proxyMap);
// 遍历 Target Map
for (Map.Entry<Class<?>, List<Proxy>> targetEntry : targetMap.entrySet()) {
// 分别获取 map 中的 key 与 value
Class<?> targetClass = targetEntry.getKey();
List<Proxy> proxyList = targetEntry.getValue();
// 创建代理实例
Object proxyInstance = ProxyManager.createProxy(targetClass, proxyList);
// 用代理实例覆盖目标实例,并放入 Bean 容器中
BeanHelper.setBeanMap(targetClass, proxyInstance);
}
} catch (Exception e) {
logger.error("aop failure",e);
}
}

private static Map<Class<?>, Set<Class<?>>> createProxyMap() throws Exception {
Map<Class<?>, Set<Class<?>>> proxyMap = new HashMap<>();
Set<Class<?>> proxyClassSet = ClassHelper.getClassSetBySuper(AspectProxy.class);
for(Class<?> proxyClass : proxyClassSet) {
if (proxyClass.isAnnotationPresent(Aspect.class)) {
Aspect aspect = proxyClass.getAnnotation(Aspect.class);
Set<Class<?>> targetClassSet = createTargetClassSet(aspect);
proxyMap.put(proxyClass, targetClassSet);
}
}
return proxyMap;
}


private static Set<Class<?>> createTargetClassSet(Aspect aspect) throws Exception {
Set<Class<?>> targetClassSet = new HashSet<>();
Class<? extends Annotation> annotation = aspect.value();
if (annotation != null && !annotation.equals(Aspect.class)) {
targetClassSet.addAll(ClassHelper.getClassSetByAnnotation(annotation));
}
return targetClassSet;
}

private static Map<Class<?>, List<Proxy>> createTargetMap(Map<Class<?>, Set<Class<?>>> proxyMap) throws Exception {
Map<Class<?>, List<Proxy>> targetMap = new HashMap<Class<?>, List<Proxy>>();
// 遍历 Proxy Map
for (Map.Entry<Class<?>, Set<Class<?>>> proxyEntry : proxyMap.entrySet()) {
// 分别获取 map 中的 key 与 value
Class<?> proxyClass = proxyEntry.getKey();
Set<Class<?>> targetClassSet = proxyEntry.getValue();
// 遍历目标类列表
for (Class<?> targetClass : targetClassSet) {
// 创建代理类(切面类)实例
Proxy baseAspect = (Proxy) proxyClass.newInstance();
// 初始化 Target Map
if (targetMap.containsKey(targetClass)) {
targetMap.get(targetClass).add(baseAspect);
} else {
List<Proxy> baseAspectList = new ArrayList<Proxy>();
baseAspectList.add(baseAspect);
targetMap.put(targetClass, baseAspectList);
}
}
}
return targetMap;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.custom.framework.proxy;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;

/**
* @author liuyi
* @date 2019/2/17
*/
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();
try {
if (intercept(cls, method, params)) {
before(cls, method, params);
result = proxyChain.doProxyChain();
after(cls, method, params);
} else {
result = proxyChain.doProxyChain();
}
} catch (Exception e) {
logger.error("proxy failure", e);
error(cls, method, params, e);
throw e;
} finally {
end();
}
return result;
}

public boolean intercept(Class<?> cls, Method method, Object[] params) throws Throwable {
return true;
}

public void begin() {

}

public void before(Class<?> cls, Method method, Object[] params) throws Throwable {

}

public void after(Class<?> cls, Method method, Object[] params) throws Throwable {

}

public void error(Class<?> cls, Method method,Object[] params, Throwable e) {

}

public void end() {

}

}
10 changes: 10 additions & 0 deletions framework/src/main/java/com/custom/framework/proxy/Proxy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.custom.framework.proxy;

/**
* @author liuyi
* @date 2019/2/16
*/
public interface Proxy {

Object doProxy(ProxyChain proxyChain) throws Throwable;
}
60 changes: 60 additions & 0 deletions framework/src/main/java/com/custom/framework/proxy/ProxyChain.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.custom.framework.proxy;

import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
* @author liuyi
* @date 2019/2/16
*/
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<>();

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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.custom.framework.proxy;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.util.List;

/**
* @author liuyi
* @date 2019/2/17
*/
public class ProxyManager {

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 );
}
});
}
}

0 comments on commit f851ea9

Please sign in to comment.