IoC 注解式开发¶
反射回顾¶
Class<?> clazz = Class.forName("Demo");
Method method = clazz.getDeclaredMethod("doSome", String.class, int.class);
Object obj = clazz.newInstance(); // 简化起见
String ret = (String) method.invoke(obj, "abc", 1);
在 xml 文件中配置好了类名和属性名,就可以:
Field field = clazz.getDeclaredField(property);
// 例如 set 方法就可以根据 ”set" 和 fieldName 拼出 methodName
Method setter = clazz.getDeclaredMathod(methodName, field.getType()); // 通过 getType 返回参数的 Class 对象
自定义注解回顾¶
- @Target:自定义注解的注解,用于修饰自定义注解可以出现的位置
- @Retention:用于标记自定义注解最终保留在哪里
- Source 只保存在源文件中
- Class 编译生成的 .class 文件中也有,但是不能被反射读取
- RUNTIME 表示可以被反射读到
@Target(value = {ElementType.Type, ElementType.Field}) // 注解可以出现在类和属性上
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value();
}
IoC 注解扫描¶
需求:给一个包,要求写一段程序扫描出这个包下的所有带有 MyAnnotation 注解的类,并实例化这些类放到 Map 集合中
public class AnnotationScan {
public static void main(String[] args) {
String packageName = "come.demo.folder";
// 正则表达式替换,注意到 . 表示任意字符,此处的 . 必须用转义符表示普通的字符
String packagePath = pakageName.replaceAll("\\.", "/");
// 拿到绝对路径
URL url = ClassLoader.getSystemClassLoader().getResource(packagePath);
String path = url.getPath();
// 获取绝对路径下的所有文件
File file = new File(path);
File[] files = file.listFiles();
for (File file : files) {
try {
String className = packageName + "." + file.getName().split("\\.")[0];
// 通过反射机制解析注解
Class<?> aClass = Class.forName(className);
// 判断类上是否有这个注解
if (aClass.isAnnotationPresent(Component.class)) {
// 获取注解
Component annotation = aClass.getAnnotation(Component.class);
String id = annotation.value();
// 有这个注解的都要创建对象
Object obj = aClass.newInstance();
beanMap.put(id, obj);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
注解分类与使用¶
控制反转:把创建对象的权力交给 Spring,把管理对象间的依赖关系的任务交给 Spring。通过依赖注入实现
声明 Bean 的注解¶
- @Component
- @Controller
- @Service
- @Repository
后三个都是 Component 的别名
@Bean¶
@Bean 通常和 @Configuration 一起使用,@Configuration 用于标识一个类是配置类。配置类的作用是定义和配置 Spring 容器中的 Bean。通过 @Configuration 注解,Spring 会将该类作为一个配置源,并处理其中定义的 Bean。
在一个方法前加上 @Bean 注解之后,Spring 会自动将方法的返回值交给 IoC 容器,使其成为 IoC 容器中的 bean 对象。
@Configuration
public class CommonConfig {
@Bean
public Resolver resolver() { // 对象名默认为方法名
return new Resolver();
}
}
在 SpringBoot 中,SpringBoot 的 spring-boot-autoconfigure
模块中包含了 Redis 的自动配置类
RedisAutoConfiguration,使得项目启动时 StringRedisTemplate 可以注入到项目中@Configuration(proxyBeanMethods = false) @ConditionalOnClass(RedisOperations.class) @EnableConfigurationProperties(RedisProperties.class) public class RedisAutoConfiguration { @Bean @ConditionalOnMissingBean(name = "redisTemplate") public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<Object, Object> template = new RedisTemplate<>(); template.setConnectionFactory(redisConnectionFactory); return template; } @Bean @ConditionalOnMissingBean public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) { return new StringRedisTemplate(redisConnectionFactory); } }
负责注入的注解¶
- @Value 初始化字段值(可以用在类的属性上,也可以用于方法上),用于注入简单类型
-
@Autowired 可以用于注入非简单类型,且单独使用时是根据类型装配。若有多个相同类型(或者接口下的多个实现类)的 Bean 会导致冲突
例子可见 Bean - 依赖注入章节
-
@Qualifier 和 @Autowired 联合使用可以根据名称装配
-
@Resource 属于 JDK 的一部分,属于 Java 规范的标准注解,默认根据名称装配,未指定名称时使用属性名作为 name,如果找不到 name 再根据类型进行装配
不是 Spring 框架内置的,Spring6 及以后需要引 jakarta.annotation(Apache 软件基金会维护)
Spring 全注解开发¶
可以编写一个类代替 Spring 框架的配置文件