diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..45d582a7c4341d8e469e1e881059579ff78b3f6b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,20 @@
+# Build and Release Folders
+bin-debug/
+bin-release/
+[Oo]bj/
+[Bb]in/
+
+# Other files and folders
+.settings/
+
+# Executables
+*.swf
+*.air
+*.ipa
+*.apk
+.idea/*
+target/*
+/src/main/java/org/needcoke/aop/test/*
+# Project files, i.e. `.project`, `.actionScriptProperties` and `.flexProperties`
+# should NOT be excluded as they contain compiler settings and other important
+# information for Eclipse / Flash Builder.
diff --git a/README.md b/README.md
index a0f8ee77fabc5203a0b8ac4f8609731c156dafa3..e33e92c7ec11c4921206e116c72a31f4d8c92481 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,8 @@
#### 介绍
needcoke-aop是基于needcoke-ioc基础上实现AOP功能的一个轻量级框架
+基于needcoke-ioc VER-0.2版本
+
#### 软件架构
软件架构说明
diff --git a/lib/needcoke-ioc.jar b/lib/needcoke-ioc.jar
new file mode 100644
index 0000000000000000000000000000000000000000..65810419395d907e622382024e65b1d3f3871b58
Binary files /dev/null and b/lib/needcoke-ioc.jar differ
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2c85e45868b970161937a2cdaf46bc75fa243a03
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,33 @@
+
+
+ 4.0.0
+
+ org.needcoke
+ needcoke-aop
+ VER-0.0.3
+ 基于needcokeVER-0.3
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 6
+ 6
+
+
+
+
+
+
+
+
+ cglib
+ cglib
+ 3.3.0
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/org/needcoke/aop/annotation/Aspect.java b/src/main/java/org/needcoke/aop/annotation/Aspect.java
new file mode 100644
index 0000000000000000000000000000000000000000..dc3b25147473f1197bd6423a70669b760b62aa74
--- /dev/null
+++ b/src/main/java/org/needcoke/aop/annotation/Aspect.java
@@ -0,0 +1,39 @@
+package org.needcoke.aop.annotation;
+
+import org.needcoke.ioc.annotation.Note;
+
+import java.lang.annotation.*;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Note("一旦被该注解标记则说明需要被AOP切的类")
+public @interface Aspect {
+
+ @Note("切什么主体")
+ CutObject target() default CutObject.DEFAULT;
+
+ @Note("被切主体的值")
+ String value() default "";
+
+ @Note("CutObject中code为3,4,5都需要入的参数")
+ String methodName() default "";
+
+ /* 类的全路径.methodName */
+ @Note("在执行前")
+ String before() default "";
+
+ /* 类的全路径.methodName */
+ @Note("不管是否正常执行完毕都会调用")
+ String afterReturning() default "";
+
+ /* 类的全路径.methodName */
+ @Note("遭遇异常执行")
+ String afterException() default "";
+
+ /* 类的全路径.methodName */
+ @Note("正常执行结束调用")
+ String afterOK() default "";
+
+ String around() default "";
+}
diff --git a/src/main/java/org/needcoke/aop/annotation/CutObject.java b/src/main/java/org/needcoke/aop/annotation/CutObject.java
new file mode 100644
index 0000000000000000000000000000000000000000..5d7f411ec7fd4f97e49e6265a0a92c1a73343a15
--- /dev/null
+++ b/src/main/java/org/needcoke/aop/annotation/CutObject.java
@@ -0,0 +1,27 @@
+package org.needcoke.aop.annotation;
+
+public enum CutObject {
+ /* 仅切一个方法 */
+ METHOD(1),
+
+ /* 仅切类的所有非静态方法 */
+ CLASS_METHOD_NOT_STATIC(2),
+
+ /* 实现了某个接口的类 */
+ CLASS_IMPLEMENT(3),
+
+ /* 继承了某个类的类 */
+ CLASS_EXTENDS(4),
+
+ /* 包路径下的所有类 */
+ PACKAGE(5),
+
+ /* 切个屁 */
+ DEFAULT(0);
+
+ private final int code;
+
+ CutObject(int code){
+ this.code = code;
+ }
+}
diff --git a/src/main/java/org/needcoke/aop/config/AOPConfig.java b/src/main/java/org/needcoke/aop/config/AOPConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..dd56f0ac044c81f3398c396160e66fb312c16535
--- /dev/null
+++ b/src/main/java/org/needcoke/aop/config/AOPConfig.java
@@ -0,0 +1,6 @@
+package org.needcoke.aop.config;
+
+public class AOPConfig {
+
+ public final static String cutAllMethodNotStaticName = "###切所有非静态方法###";
+}
diff --git a/src/main/java/org/needcoke/aop/handle/AOPHandle.java b/src/main/java/org/needcoke/aop/handle/AOPHandle.java
new file mode 100644
index 0000000000000000000000000000000000000000..f890932e6f105a51d757f5c2260fa5dfa59e95e0
--- /dev/null
+++ b/src/main/java/org/needcoke/aop/handle/AOPHandle.java
@@ -0,0 +1,209 @@
+package org.needcoke.aop.handle;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
+import net.sf.cglib.proxy.Enhancer;
+import org.needcoke.aop.annotation.Aspect;
+import org.needcoke.aop.annotation.CutObject;
+import org.needcoke.aop.config.AOPConfig;
+import org.needcoke.aop.interceptor.NeedCokeAOPInterceptor;
+import org.needcoke.aop.interceptor.TargetMethod;
+import org.needcoke.ioc.core.ContextBean;
+import org.needcoke.ioc.core.ContextHolder;
+import org.needcoke.ioc.handle.Handle;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.List;
+
+public class AOPHandle implements Handle {
+ private ContextHolder holder;
+
+ @Override
+ public int handle(ContextHolder holder, Object... params) {
+ this.holder = holder;
+ for (Class> aClass : holder.componentMap.keySet()) {
+ Aspect annotationAspect = aClass.getAnnotation(Aspect.class);
+ if (null != annotationAspect) {
+ aspect(annotationAspect, holder.componentMap.get(aClass), aClass);
+ }
+ }
+
+
+ /* 使用AOP对象替换 */
+ return 0;
+ }
+
+ private void aspect(Aspect annotationAspect, Object component, Class> clz) {
+ /* 切什么 */
+ CutObject target = annotationAspect.target();
+ String value = annotationAspect.value();
+ String methodName = annotationAspect.methodName();
+ TargetMethod around = fullLocationToTargetMethod(clz, annotationAspect.around());
+ TargetMethod before = fullLocationToTargetMethod(clz, annotationAspect.before());
+ TargetMethod afterOK = fullLocationToTargetMethod(clz, annotationAspect.afterOK());
+ TargetMethod afterException = fullLocationToTargetMethod(clz, annotationAspect.afterException());
+ TargetMethod afterFinally = fullLocationToTargetMethod(clz, annotationAspect.afterReturning());
+
+ if (target == CutObject.METHOD) {
+ TargetMethod targetMethod = fullLocationToTargetMethod(clz, value);
+ Enhancer enhancer = new Enhancer();
+ enhancer.setSuperclass(targetMethod.getComponent().getClass());
+ enhancer.setCallback(new NeedCokeAOPInterceptor(targetMethod.getMethod().getName(),
+ before, around, afterOK, afterException, afterFinally));
+ Object o = enhancer.create();
+
+ ContextBean bean = new ContextBean()
+ .setProxy(true)
+ .setValue(o)
+ .setClz(targetMethod.getComponent().getClass())
+ .setName(targetMethod.getComponent().getClass().getName() + "#needcoke代理对象");
+ holder.proxyComponentMap.put(targetMethod.getComponent().getClass(), bean);
+ }
+ else if (target == CutObject.CLASS_METHOD_NOT_STATIC) {
+ TargetMethod targetMethod = fullLocationToTargetClass(clz, value);
+ Enhancer enhancer = new Enhancer();
+ enhancer.setSuperclass(targetMethod.getComponent().getClass());
+
+ enhancer.setCallback(new NeedCokeAOPInterceptor(AOPConfig.cutAllMethodNotStaticName,
+ before, around, afterOK, afterException, afterFinally));
+ Object o = enhancer.create();
+
+ ContextBean bean = new ContextBean()
+ .setProxy(true)
+ .setValue(o)
+ .setClz(targetMethod.getComponent().getClass())
+ .setName(targetMethod.getComponent().getClass().getName() + "#needcoke代理对象");
+ holder.proxyComponentMap.put(targetMethod.getComponent().getClass(), bean);
+ }
+ else if(target == CutObject.CLASS_IMPLEMENT || target == CutObject.CLASS_EXTENDS){
+ try {
+ Class interfaceClass = Class.forName(value);
+ Collection values = holder.idBeanMap.values();
+ for (ContextBean contextBean : values) {
+ if(interfaceClass.isInstance(contextBean.value)){
+ TargetMethod targetMethod = fullLocationToTargetClass(contextBean.clz, contextBean.getClz().getName());
+ Enhancer enhancer = new Enhancer();
+ enhancer.setSuperclass(targetMethod.getComponent().getClass());
+ if(StrUtil.isBlank(methodName)){
+ methodName = AOPConfig.cutAllMethodNotStaticName;
+ }
+ enhancer.setCallback(new NeedCokeAOPInterceptor(methodName,
+ before, around, afterOK, afterException, afterFinally));
+ Object o = enhancer.create();
+
+ ContextBean bean = new ContextBean()
+ .setProxy(true)
+ .setValue(o)
+ .setClz(targetMethod.getComponent().getClass())
+ .setName(targetMethod.getComponent().getClass().getName() + "#needcoke代理对象");
+ holder.proxyComponentMap.put(targetMethod.getComponent().getClass(), bean);
+ }
+ }
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ }
+ }else if(target == CutObject.PACKAGE){
+ Collection values = holder.idBeanMap.values();
+ for (ContextBean contextBean : values) {
+ if(contextBean.clz.getName().startsWith(value.replace("*",""))){
+ TargetMethod targetMethod = fullLocationToTargetClass(contextBean.clz, contextBean.getClz().getName());
+ Enhancer enhancer = new Enhancer();
+ enhancer.setSuperclass(targetMethod.getComponent().getClass());
+ if(StrUtil.isBlank(methodName)){
+ methodName = AOPConfig.cutAllMethodNotStaticName;
+ }
+ enhancer.setCallback(new NeedCokeAOPInterceptor(methodName,
+ before, around, afterOK, afterException, afterFinally));
+ Object o = enhancer.create();
+
+ ContextBean bean = new ContextBean()
+ .setProxy(true)
+ .setValue(o)
+ .setClz(targetMethod.getComponent().getClass())
+ .setName(targetMethod.getComponent().getClass().getName() + "#needcoke代理对象");
+ holder.proxyComponentMap.put(targetMethod.getComponent().getClass(), bean);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * @param clz Aspect注解标注的类
+ * @param fullLocation 方法的全路径 org.needcoke.aop.handle.AOPHandle#fullLocationToTargetMethod
+ * @return {@link TargetMethod}
+ * @author Gilgamesh
+ * @date 2021/9/16 9:16
+ **/
+ private TargetMethod fullLocationToTargetMethod(Class> clz, String fullLocation) {
+ if (StrUtil.isBlank(fullLocation)) {
+ return new TargetMethod();
+ }
+ String classFullName = "";
+ String methodName = "";
+ if (fullLocation.contains(".")) {
+ StringBuilder clzFullName = new StringBuilder();
+ String[] split = fullLocation.split("\\.");
+ for (int i = 0; i < split.length - 1; i++) {
+ clzFullName.append(split[i] + ".");
+ }
+ classFullName = clzFullName.substring(0, clzFullName.length() - 1);
+ methodName = split[split.length - 1];
+ } else {
+ /* fullLocation不是全路径只有方法名,则代表methodName是当前注解标注类中的方法 */
+ methodName = fullLocation;
+ classFullName = clz.getName();
+ }
+ TargetMethod targetMethod = new TargetMethod();
+ List contextBeans = holder.fullNameBeanContext.get(classFullName);
+ ContextBean contextBean = null;
+ if (CollUtil.isNotEmpty(contextBeans)) {
+ contextBean = contextBeans.get(0);
+ } else {
+ try {
+ Class> aClass = Class.forName(classFullName);
+ Object aspectO = aClass.newInstance();
+ contextBean = new ContextBean();
+ contextBean.setClz(aClass);
+ contextBean.setValue(aspectO);
+ contextBean.setName(aClass.getName());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ targetMethod.setComponent(contextBean.value);
+ Class aspectClz = contextBean.clz;
+ Method method = null;
+ try {
+ method = aspectClz.getMethod(methodName);
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ }
+ targetMethod.setMethod(method);
+ return targetMethod;
+ }
+
+ private TargetMethod fullLocationToTargetClass(Class> clz, String fullLocation) {
+ TargetMethod targetMethod = new TargetMethod();
+ if (StrUtil.isBlank(fullLocation)) {
+ List> bean = holder.getBean(clz);
+ if (CollUtil.isNotEmpty(bean)) {
+ targetMethod.setComponent(bean.get(0));
+ }
+ } else {
+ List contextBeans = holder.fullNameBeanContext.get(fullLocation);
+ if (CollUtil.isNotEmpty(contextBeans)) {
+ ContextBean contextBean = contextBeans.get(0);
+ targetMethod.setComponent(contextBean.value);
+ }
+ }
+ if(targetMethod.getComponent() == null){
+ throw new RuntimeException("AOP value 的值错误,应该是类的全路径!");
+ }
+ Method[] methods = clz.getMethods();
+ if (methods.length > 0) {
+ targetMethod.setMethod(clz.getMethods()[0]);
+ }
+ return targetMethod;
+ }
+}
diff --git a/src/main/java/org/needcoke/aop/interceptor/NeedCokeAOPInterceptor.java b/src/main/java/org/needcoke/aop/interceptor/NeedCokeAOPInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..b14aa9a5827cb9ac936e1a5ea342d4bd65fdb37f
--- /dev/null
+++ b/src/main/java/org/needcoke/aop/interceptor/NeedCokeAOPInterceptor.java
@@ -0,0 +1,52 @@
+package org.needcoke.aop.interceptor;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import net.sf.cglib.proxy.MethodInterceptor;
+import net.sf.cglib.proxy.MethodProxy;
+import org.needcoke.aop.config.AOPConfig;
+
+import java.lang.reflect.Method;
+
+@Data
+@Accessors(chain = true)
+@NoArgsConstructor
+@AllArgsConstructor
+public class NeedCokeAOPInterceptor implements MethodInterceptor {
+
+ private String methodName = "";
+
+ private TargetMethod before = new TargetMethod();
+
+ private TargetMethod around = new TargetMethod();
+
+ private TargetMethod afterOK = new TargetMethod();
+
+ private TargetMethod afterException = new TargetMethod();
+
+ private TargetMethod afterReturning = new TargetMethod();
+
+ @Override
+ public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
+ if (!method.getName().equals(methodName) && !methodName.equals(AOPConfig.cutAllMethodNotStaticName)) {
+ return methodProxy.invokeSuper(o, objects);
+ }
+ around.invoke();
+ before.invoke();
+ try {
+ Object invoke = methodProxy.invokeSuper(o, objects);
+ around.invoke();
+ afterOK.invoke();
+ return invoke;
+ } catch (Throwable e) {
+ e.printStackTrace();
+ afterException.invoke();
+ throw new RuntimeException(o.getClass().getName() + ", method= " + method.getName() + " ,AOP失败!");
+ } finally {
+ afterReturning.invoke();
+ }
+
+ }
+}
diff --git a/src/main/java/org/needcoke/aop/interceptor/TargetMethod.java b/src/main/java/org/needcoke/aop/interceptor/TargetMethod.java
new file mode 100644
index 0000000000000000000000000000000000000000..e14cd2d8f6610f00649c217bf5a15ee477979b81
--- /dev/null
+++ b/src/main/java/org/needcoke/aop/interceptor/TargetMethod.java
@@ -0,0 +1,20 @@
+package org.needcoke.aop.interceptor;
+
+import lombok.Data;
+import java.lang.reflect.Method;
+
+@Data
+public class TargetMethod {
+
+ private Object component;
+
+ private Method method;
+
+ private Object[] ags;
+
+ public void invoke() throws Throwable {
+ if (null != component && null != method) {
+ method.invoke(component, ags);
+ }
+ }
+}
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
new file mode 100644
index 0000000000000000000000000000000000000000..3ec4444e133098b9b77e2a14f9fb0717db1cbcf9
--- /dev/null
+++ b/src/main/resources/application.yml
@@ -0,0 +1,3 @@
+
+
+abc: dffwef
\ No newline at end of file