Java自定义Bean注解,实现类似Spring中的依赖注入(三)

仅仅是获取到注解信息还不够,还需要根据得到的信息做出一些反应,这样才能让人眼前一亮,心中明悟: 原来注解时这么用的

依赖注入容器的注解实现

一,定义两个表示电脑CPU与GraphicsCard的接口

package org.jy.sso.cas.data.server.system.annoAndReflect;

public interface CPU { // 描述CPU
    void calculate(); // 接口方法
}

package org.jy.sso.cas.data.server.system.annoAndReflect;

public interface GraphicsCard { // 描述显卡的接口
    void display();
}

二,编写上面接口的实现类

 

package org.jy.sso.cas.data.server.system.annoAndReflect;

public class IntelCPU  implements CPU{
    @Override
    public void calculate() {
        System.out.println("Intel CPU calculate.");
    }
}

package org.jy.sso.cas.data.server.system.annoAndReflect;

public class NVIDIACard implements GraphicsCard{
    @Override
    public void display() {
        System.out.println("Display something");
    }
}

三,定义@Bean注解

package org.jy.sso.cas.data.server.system.annoAndReflect;

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

@Target({ElementType.METHOD,ElementType.FIELD}) // 该注解可以用在那些地方
@Retention(RetentionPolicy.RUNTIME) // 注解的什么周期
public @interface Bean {
    Class<?> value(); // 元素的值是一个Class对象
}

四,编写注解处理器,实现依赖注入

package org.jy.sso.cas.data.server.system.annoAndReflect;

import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 注解工厂处理器
 */
public class AnnotationFactory {
    /**
     * 根据指定的Class对象,创建对应类的对象,
     * 同时读取类中的@Bean注解,根据注解信息,实现依赖注入
     * 该方法演示了注解信息获取与反射相关的方法
     *
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T getBean(Class<T> clazz) {
        T obj = null;
        try {
            // 创建参数clazz代表的类的对象
            obj = clazz.getConstructor().newInstance(); // 通过构造对象(Constructor)的静态方法newInstance()对象
            // 得到类中所有声明的方法
            Method[] methods = clazz.getDeclaredMethods();// 获得所有的方法描述类Method,
            for (Method method : methods) {
                Object implObject = getImplObject(method);// Method 实现了AnnotationElement接口,该方法取到筛选作用
                if (implObject != null) {
                    // 调用方法,传入依赖的对象
                    method.invoke(obj, implObject);
                }
            }
            // 得到类中声明的所有的字段
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                Object implObject = getImplObject(field); // 只获取到标准有@Bean注解的所有域
                if (implObject != null) {
                    // 设置值
                    field.setAccessible(Boolean.TRUE);
                    field.set(obj, implObject); // 执行set方法及对应的值
                    field.setAccessible(Boolean.FALSE);
                }
            }
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            e.printStackTrace();
        }

        return obj;
    }

    /**
     * 使用辅助方法,根据Bean注解的元素的值创建对应的对象,
     * Field和Method类都实现了AnnotationElement接口
     * 该实现类只处理标记有@Bean注解的方法
     *
     * @param element
     * @return
     * @throws NoSuchMethodException
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    private static Object getImplObject(AnnotatedElement element)
            throws NoSuchMethodException,
            InstantiationException,
            IllegalAccessException,
            InvocationTargetException { // 必须声明这些异常,否则clazz.getDeclaredConstructor().newInstance(); 必需要方法参数
        if (element.isAnnotationPresent(Bean.class)) { // 判断element注解实现类是否有Bean这个注解
            Bean beanAnnotation = element.getDeclaredAnnotation(Bean.class);
            Class<?> clazz = beanAnnotation.value();
            return clazz.getDeclaredConstructor().newInstance(); // 返回的是一个标注有@Bean注解的对象
        }
        return null;
    }

}

五,使用注解@Bean标注类,

package org.jy.sso.cas.data.server.system.annoAndReflect;

/**
 * 主要的牌子
 */
public class MainBoard {

    @Bean(IntelCPU.class) // 依赖注入
    private CPU cpu;

    private GraphicsCard graphicsCard;

    @Bean(NVIDIACard.class) // 依赖注入
    public void setGraphicsCard(GraphicsCard graphicsCard) {
        this.graphicsCard = graphicsCard;
    }

    // 验证对象是否自动创建,依赖注入
    public void run() {
        System.out.println("Starting computer...");
        cpu.calculate();
        graphicsCard.display();
    }
}

六,执行下面的类,验证是否依赖注入

package org.jy.sso.cas.data.server.system.annoAndReflect;

/**
 * 演示使用注解实现依赖注入
 */
public class ComputerRun {
    public static void main(String[] args){
        MainBoard mainBoard = AnnotationFactory.getBean(MainBoard.class);
        mainBoard.run();
    }
}

运行结果如下:
Starting computer...
Intel CPU calculate.
Display something

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值