这里先说一下,部分同学接触注解可能都是在spring相关学习和使用中,但其实注解本身和spring并没有什么必然关系,注解是java本身的具有的功能,在重写对象方法的时候大家应该都见过,只是可能并没有在意。注解的本质我个人理解就是一种轻量级的特殊接口,被以注解的形式使用,直接套在对象的头上,给对象增加一个特殊标识,方便在反射中进行识别。
所以这里大家要明白一点,spring或者其相关框架springboot这样的,都只会自动识别和处理自身设定的注解,我们自己写的注解只能我们自己来进行处理。不要抄了一个注解改了个名字,然后使用发现没有效果觉得奇怪。注解只能标识,本身没有处理能力。不要觉得我这是废话,因为我就见过不止一个人在学习注解的时候这么干。
首先说一下注解的基本样式:
import java.lang.annotation.*;
//注解适用范围
@Target({ElementType.TYPE})
//注解保留策略,编译前,编译后,运行时(默认为编译后)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface MyAnnotaionBean {}
有人会问,上面四个注解是啥?可以不要吗?可以不写,因为他们都是有默认值的,但是要看你这个注解是打算怎么用,比如我这个是用来标记特定对象,那么如果不加@Retention(RetentionPolicy.RUNTIME) 这句,在程序启动后,运行中通过反射就无法判断是那个对象被标识,因为在运行时注解已经被抛弃了。
这几个注解都是java定义的元注解,可以理解成java对注解进行的规范要求,是注解本身的属性。@Target声明注解的使用范围,是对象头,还是属性或者函数和其他位置。@Retention声明注解保留策略,也可以理解为生命周期。@Documented声明该注解应该被标注为对象成员公共API,可以被javadoc等工具文档化。@Inherited声明该注解是否被对象的子类继承。
下面就用最基本的依赖注入来说明一下自定义注解,为了方便我使用了springboot生成项目,这样可以忽略对象生成的过程。下面先是注入用的注解:
@Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface MyAutowired { String value() default ""; }
上面的MyAnnotaionBean是用来标记被添加了注解的对象,避免轮询全部对象,既然标记了,那当然要做一下记录,于是写了一个静态集合用来记录被标记的对象:
public class MyAnnotationClassName {
public static List<String> classNames = new ArrayList<String>();
}
下面我们在springboot的启动main函数中增加相关代码,为了省略对象实例化部分,我把对象加了spring注解自动实例化,只是对注入的部分进行了自定义:
public static void main(String[] args) {
//获取容器入口
ConfigurableApplicationContext cac = SpringApplication.run(MyStydySpringbootDemoApplication.class, args);
//判断加特定注解的对象数量
if(MyAnnotationClassName.classNames.size() > 0){
for(String className : MyAnnotationClassName.classNames){
//从容器中提取对象
Object bean = cac.getBean(className);
//属性
Field[] fld = bean.getClass().getDeclaredFields();
for(Field fs : fld){
//判断属性注解
if(!fs.isAnnotationPresent(MyAutowired.class)) { continue; }
MyAutowired myAuto = fs.getAnnotation(MyAutowired.class);
//获取注解属性值
String perpam = myAuto.value();
if(perpam == null || "".equals(perpam.trim())) {
//注解无属性值则直接使用属性名称
perpam = fs.getName();
}
//给参数赋值
try {
//private属性需要设置后才能注入
fs.setAccessible(true);
System.out.println("MyAutowired注入"+perpam);
//注入
fs.set(bean, cac.getBean(perpam));
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
为了给MyAnnotationClassName中写入值,我偷了下懒,直接利用Processor在bean初始化时进行记录:
@Component
public class MyProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(bean.getClass().isAnnotationPresent(MyAnnotaionBean.class)){
MyAnnotationClassName.classNames.add(beanName);
}
return bean;
}
最后就是直接的使用了:
@MyAnnotaionBean @RestController public class MyController { @MyAutowired(value = "userDaoMySql") private IUserDao userDao; @MyAutowired(value = "UserInfo") private UserInfo uinfo; @RequestMapping("/user") public String getUser(@RequestParam Integer userid){ UserDTO ud = userDao.findUserById(userid); return ud.getUserName(); } @RequestMapping("/userAll") public String getAllUser(){ List<UserDTO> userDTO = userDao.getAllUser(); JSONPObject jo = new JSONPObject("",userDTO); return jo.toString(); } @RequestMapping("/skill") public String getSkill(){ return uinfo.getUserName(); } }
之后我们来看看效果。

从运行来看注入操作已经进行了,那么看前端返回。


返回正确,注入成功了。
本文详细介绍了如何在Spring Boot中使用自定义注解进行对象的依赖注入,包括注解的定义、元注解的作用和实际应用示例,展示了如何通过注解标记对象并进行自动识别和处理。
497

被折叠的 条评论
为什么被折叠?



