手动编码实现spring框架IOC和AOP功能

自研的一个微型java开发框架
类似spring 实现了IOC容器托管与AOP
仓库地址: https://github.com/KcangYan/BarnFramework

主启动类入口

import com.kcang.main.MiniFramework;

public class ApplicationStart {
    public static void main(String[] args) {
        BarnFramework.run(ApplicationStart.class, args);
    }
}

框架会根据ApplicationStart.class所在的包的路径,去扫描包下所有的类来实现具体的注解和方法。

添加主启动方法

@ManagedInstance
public class Test20220324 extends MainRunnable {
    private static Logger myLogger = LoggerFactory.getLogger(Test20220324.class);

    public Test20220324(){
            super.order = 2;
        }

    @Override
    public void run() {
        run("另一个run");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        myLogger.info("Test20220324");
    }

    public void run(String name){
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        myLogger.info(name);
    }
}

通过继承抽象类MainRunnable 实现run方法,并将该类通过@ManagedInstance注解交给容器托管即可。
当在主启动类的包下扫描到继承了MainRunnable类的子类则会运行该类下的run()方法

ico 单例管理容器

1. 容器托管使用方法

import com.kcang.annotation.ioc.bean.ManagedInstance;
import com.kcang.annotation.ioc.InjectInstance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@ManagedInstance
public class Test20220326_1 {

    private static Logger myLogger = LoggerFactory.getLogger(Test20220326_1.class);
    @InjectInstance
    private Test20220326_2 test20220326_2;

    public void run(){
        myLogger.info(" test 20220326-1 " + test20220326_2);
    }
}

通过@ManagedInstance 注解在类上方标识该注解 同时也可以添加name属性自定义bean单例名称

import com.kcang.annotation.ioc.bean.ManagedInstance;
import com.kcang.annotation.ioc.InjectInstance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@ManagedInstance(name = "Test20220326_1")
public class Test20220326_1 {

    private static Logger myLogger = LoggerFactory.getLogger(Test20220326_1.class);
    @InjectInstance
    private Test20220326_2 test20220326_2;

    public void run(){
        myLogger.info(" test 20220326-1 " + test20220326_2);
    }
}

也可以通过声明配置类托管

 @Configuration
 public class ConfigBean {
     @Barn(name = "TestHashMap")
     public HashMap<String, String> hashMap(){
         return new HashMap<String, String>();
     }
     @Barn(name = "TestArrayList")
     public List list(){
         return new ArrayList();
     }
 }

还有@Component @Service等注解 也是将当前类托管至ioc容器

2. 单例实例的使用

@InjectInstance
private Test20220326_2 test20220326_2;

@InjectInstance(name="Test20220326_2")
private Test20220326_2 test20220326_2;

可以通过在属性对象上方添加注解@InjectBean 使用。会将容器中的单例注入到属性中,直接使用即可

3. 使用注意

所有的Aop 注解和自定义实现 以及 @InjectInstance 都依赖于该实例对象是托管至ioc容器中的实例。
如果所需要的对象必须不能是单例的话 有两种使用办法 
1. 利用@Bean注解 把所有需要的对象都一一Bean出来到容器里去用,这样aop 和 ioc的注解都不影响
2. 使用AttachFunc.newInstance(Class cls)方法创建对象,该方法创建的对象会注入bean到属性里使用 并且实现aop注解

Aop 方法代理注解实现

声明注解类

 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
 @Retention(RetentionPolicy.RUNTIME)
 @Target(value = {ElementType.METHOD})
 public @interface Test1 {
     String value() default "";
 }

继承AopMethodProxy抽象类 并在类上方使用注解@AopAnnotationImpl,并将该类指向你自定义的注解作为该注解的实现类
可以通过order来提高当前注解的执行顺序,order越小执行顺序越高,默认是10

 @AopAnnotationImpl(AopAnnotation = Test1.class, order=5)
 public class Test1Impl extends AopMethodProxy {
     private static Logger myLogger = LoggerFactory.getLogger(Test1Impl.class);
 
     private Test1 test1;
 
     @Override
     public void setAnnotation(Object annotation) {
         this.test1 = (Test1) annotation;
     }
 
     @Override
     public void before(Object[] args) {
         myLogger.info(Arrays.toString(args));
     }
 
     @Override
     public void after(Object result) {
 
     }
 }

具体方法的使用和定义,可以去AopMethodProxy类里面去看注释

当多个aop代理实现类代理同一个方法,需要在实现类的注解@AopAnnotationImpl(AopAnnotation = Test1.class, order = 1)
中增加order属性,order越小 层级越高

 @AopAnnotationImpl(AopAnnotation = Test1.class, order = 1)
 public class Test1Impl extends AopMethodProxy {
     private static Logger myLogger = LoggerFactory.getLogger(Test1Impl.class);
 
     private Test1 test1;
 
     @Override
     public void setAnnotation(Object annotation) {
         this.test1 = (Test1) annotation;
     }
 
 
     @Override
     public void before(Object[] args) {
         myLogger.info("Test1 before "+Arrays.toString(args));
     }
 
     @Override
     public Object around(AopMethod aopMethod) throws Throwable {
         myLogger.info("Test1 around1");
         Object result = aopMethod.methodRun();
         myLogger.info("Test1 get result " + result);
         myLogger.info("Test1 around2");
         return "Test1";
     }
 
     @Override
     public void after(Object result) {
         myLogger.info("Test1 after "+result);
     }
 }
  
 @AopAnnotationImpl(AopAnnotation = Test2.class, order = 2)
 public class Test2Impl extends AopMethodProxy {
     private static Logger myLogger = LoggerFactory.getLogger(Test2Impl.class);
 
     private Test2 test2;
 
     @Override
     public void setAnnotation(Object annotation) {
         this.test2 = (Test2) annotation;
     }
 
     @Override
     public void before(Object[] args) {
         myLogger.info("Test2 before "+ Arrays.toString(args));
     }
 
     @Override
     public Object around(AopMethod aopMethod) throws Throwable {
         myLogger.info("Test2 around1");
         Object result = aopMethod.methodRun();
         myLogger.info("Test2 get result " + result);
         myLogger.info("Test2 around2");
         return "Test2";
     }
 
     @Override
     public void after(Object result) {
         myLogger.info("Test2 after "+result);
     }
 }
 
 @AopAnnotationImpl(AopAnnotation = Test3.class, order = 3)
 public class Test3Impl extends AopMethodProxy {
     private static Logger myLogger = LoggerFactory.getLogger(Test3Impl.class);
     @Override
     public void setAnnotation(Object annotation) {
 
     }
 
     @Override
     public void before(Object[] args) {
         myLogger.info("Test3 before "+ Arrays.toString(args));
     }
 
     @Override
     public Object around(AopMethod aopMethod) throws Throwable {
         myLogger.info("Test3 around1");
         Object result = aopMethod.methodRun();
         myLogger.info("Test3 get result " + result);
         myLogger.info("Test3 around2");
         return "Test3";
     }
 
     @Override
     public void after(Object result) {
         myLogger.info("Test3 after "+result);
     }
 }
 
 @Test1
 @Test2
 @Test3
 public String run(String s, int x, int y){
     myLogger.info("Test0330_1 " + s+" x="+x+" y="+y);
     return "Test0330_1 " + s+" x="+x+" y="+y;
 }
 
 2022-03-31 22:43:17.554 [main] INFO  com.kcang.test.annotation.Test1Impl - Test1 before [kcang, 1, 2]
 2022-03-31 22:43:17.554 [main] INFO  com.kcang.test.annotation.Test1Impl - Test1 around1
 2022-03-31 22:43:17.554 [main] INFO  com.kcang.test.annotation.Test2Impl - Test2 before [kcang, 1, 2]
 2022-03-31 22:43:17.554 [main] INFO  com.kcang.test.annotation.Test2Impl - Test2 around1
 2022-03-31 22:43:17.555 [main] INFO  com.kcang.test.annotation.Test3Impl - Test3 before [kcang, 1, 2]
 2022-03-31 22:43:17.555 [main] INFO  com.kcang.test.annotation.Test3Impl - Test3 around1
 2022-03-31 22:43:17.564 [main] INFO  com.kcang.test.Test0330_1 - Test0330_1 kcang x=1 y=2
 2022-03-31 22:43:17.564 [main] INFO  com.kcang.test.annotation.Test3Impl - Test3 get result Test0330_1 kcang x=1 y=2
 2022-03-31 22:43:17.564 [main] INFO  com.kcang.test.annotation.Test3Impl - Test3 around2
 2022-03-31 22:43:17.564 [main] INFO  com.kcang.test.annotation.Test3Impl - Test3 after Test3
 2022-03-31 22:43:17.564 [main] INFO  com.kcang.test.annotation.Test2Impl - Test2 get result Test3
 2022-03-31 22:43:17.564 [main] INFO  com.kcang.test.annotation.Test2Impl - Test2 around2
 2022-03-31 22:43:17.564 [main] INFO  com.kcang.test.annotation.Test2Impl - Test2 after Test2
 2022-03-31 22:43:17.564 [main] INFO  com.kcang.test.annotation.Test1Impl - Test1 get result Test2
 2022-03-31 22:43:17.564 [main] INFO  com.kcang.test.annotation.Test1Impl - Test1 around2
 2022-03-31 22:43:17.564 [main] INFO  com.kcang.test.annotation.Test1Impl - Test1 after Test1
 2022-03-31 22:43:17.564 [main] INFO  com.kcang.test.Test - Test1

修改代理方法入参

 aopMethod.setArgs(new Object[]{"test1", 1, 1});

当你想要你的aop实现类的入参修改作为最终代理方法的真正入参,则可以

 aopMethod.setArgs(new Object[]{"test1", 1, 1},this);

修改代理方法返回值则直接在around方法里return你的结果即可
如果你想要你的aop实现所返回的结果作为代理方法的最终返回,则可以

 aopMethod.setResult("Test3", this);

已实现的工具注解

   @AsyncRunnable
   @Override
   public void run() {
       run("另一个run");
       try {
           Thread.sleep(5000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       myLogger.info("Test20220324");
   }

   @AsyncRunnable(type = AsyncType.Synchronous)
   public void run(String name){
       try {
           Thread.sleep(5000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       myLogger.info(name);
   }
   
   //使用自定义的线程池代替默认的线程池
   @AsyncRunnable(type = AsyncType.CustomThreadPool, name = "ThreadPoolExecutor")
   public void run(String name){
       try {
           Thread.sleep(5000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       myLogger.info(name);
   }       

@AsyncRunnable注解会将当前方法的运行交给内置线程池做异步运行,具体线程池可以去看GlobalThreadPoolExecutor类
的注解和线程池参数配置

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值