diff --git a/spring-annotation/pom.xml b/spring-annotation/pom.xml index 1047da5..5511772 100644 --- a/spring-annotation/pom.xml +++ b/spring-annotation/pom.xml @@ -23,6 +23,7 @@ spring-annotation-conditional spring-annotation-value spring-annotation-autowired + spring-annotation-profile \ No newline at end of file diff --git a/spring-annotation/spring-annotation-profile/README.md b/spring-annotation/spring-annotation-profile/README.md new file mode 100644 index 0000000..a16511d --- /dev/null +++ b/spring-annotation/spring-annotation-profile/README.md @@ -0,0 +1 @@ +## TODO \ No newline at end of file diff --git a/spring-annotation/spring-annotation-profile/pom.xml b/spring-annotation/spring-annotation-profile/pom.xml new file mode 100644 index 0000000..4733a76 --- /dev/null +++ b/spring-annotation/spring-annotation-profile/pom.xml @@ -0,0 +1,19 @@ + + + + spring-annotation + com.xcs.spring + 0.0.1-SNAPSHOT + + 4.0.0 + + spring-annotation-profile + + + 11 + 11 + + + \ No newline at end of file diff --git a/spring-jsr/pom.xml b/spring-jsr/pom.xml index 875f2cb..97e424a 100644 --- a/spring-jsr/pom.xml +++ b/spring-jsr/pom.xml @@ -30,6 +30,11 @@ javax.inject 1 + + jakarta.annotation + jakarta.annotation-api + 1.3.5 + \ No newline at end of file diff --git a/spring-jsr/spring-jsr250-resource/README.md b/spring-jsr/spring-jsr250-resource/README.md index a16511d..6146218 100644 --- a/spring-jsr/spring-jsr250-resource/README.md +++ b/spring-jsr/spring-jsr250-resource/README.md @@ -1 +1,198 @@ -## TODO \ No newline at end of file +## @Resource + + + +### 一、基本信息 + +✒️ **作者** - Lex 📝 **博客** - [我的CSDN](https://blog.csdn.net/duzhuang2399/article/details/133887864) 📚 **文章目录** - [所有文章](https://github.com/xuchengsheng/spring-reading) 🔗 **源码地址** - [@Resource源码](https://github.com/xuchengsheng/spring-reading/blob/master/spring-jsr/spring-jsr250-resource) + +### 二、接口描述 + +`@Resource` 注解是由 JSR-250: Common Annotations for the Java Platform 规范定义的。这个规范定义了一组跨多个 Java 技术(如 Java EE 和 Java SE)的公共注解。 + +### 三、接口源码 + +`@Resource` 注解的目的是为了声明和注入应用程序所需的外部资源,从而允许容器在运行时为应用程序组件提供这些资源。 + +```java +/** + * 标注需要注入的资源的注解。 + * 这个注解可以用于类、字段和方法上,指示容器为其注入资源。 + */ +@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Repeatable(Resources.class) +public @interface Resource { + + /** + * 资源的 JNDI 名称。 + * + * @return 资源名称。 + */ + String name() default ""; + + /** + * JNDI 查询名称,用于运行时查找资源。 + * + * @return JNDI 查询名称。 + */ + String lookup() default ""; + + /** + * 资源的期望类型。默认为 Object,意味着类型不特定。 + * + * @return 资源类型。 + */ + Class type() default Object.class; + + /** + * 资源的身份验证类型。 + * + * @return 身份验证类型。 + */ + Resource.AuthenticationType authenticationType() default Resource.AuthenticationType.CONTAINER; + + /** + * 标示资源是否可以被多个客户端共享。 + * + * @return 如果资源可以被共享则返回 true,否则返回 false。 + */ + boolean shareable() default true; + + /** + * 与资源环境引用关联的产品特定的名称。 + * + * @return 映射名称。 + */ + String mappedName() default ""; + + /** + * 对资源的简要描述。 + * + * @return 资源描述。 + */ + String description() default ""; + + /** + * 身份验证类型的枚举。 + * CONTAINER: 容器管理身份验证。 + * APPLICATION: 应用程序管理身份验证。 + */ + public static enum AuthenticationType { + CONTAINER, + APPLICATION; + } +} +``` + +### 四、主要功能 + +1. **资源定位** + + 通过 `name` 和 `lookup` 属性,`@Resource` 可以定位到特定的资源,如 JNDI 中的一个数据库连接。 +2. **类型指定** + + 通过 `type` 属性,它允许指定所需资源的具体Java类型,确保注入的资源与预期类型匹配,从而提供类型安全。 +3. **身份验证策略** + + `authenticationType` 属性允许开发者选择资源的身份验证方式,决定是由容器还是应用程序来进行身份验证。 +4. **共享策略** + + 通过 `shareable` 属性,它指定资源是否可以在多个客户端或组件之间共享。 +5. **供应商特定名称** + + `mappedName` 属性可以提供与资源关联的供应商或平台特定的名称,增加部署的灵活性。 +6. **描述信息** + + 通过 `description` 属性,为资源提供了简要描述,有助于开发者和系统管理员理解其用途。 + +### 五、最佳实践 + +首先来看看启动类入口,上下文环境使用`AnnotationConfigApplicationContext`(此类是使用Java注解来配置Spring容器的方式),构造参数我们给定了一个`MyConfiguration`组件类。然后从Spring上下文中获取一个`MyController`类型的bean并调用了`showService`方法, + +```java +public class ResourceApplication { + + public static void main(String[] args) { + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class); + MyController controller = context.getBean(MyController.class); + controller.showService(); + } +} +``` + +在`MyConfiguration`类中,使用了`@ComponentScan("com.xcs.spring")`注解告诉 Spring 在指定的包(在这里是 "`com.xcs.spring`")及其子包中搜索带有 `@Component`、`@Service`、`@Repository` 和 `@Controller` 等注解的类,并将它们自动注册为 beans。这样,spring就不必为每个组件明确写一个 bean 定义。Spring 会自动识别并注册它们。 + +```java +@Configuration +@ComponentScan("com.xcs.spring") +public class MyConfiguration { + +} +``` + +Spring 容器在初始化 `MyController` 时,我们使用了`@Resource`注解,会自动注入一个 `MyService` 类型的 bean 到 `myService` 字段。 + +```java +@Controller +public class MyController { + + @Resource(name="myService") + private MyService myService; + + public void showService(){ + System.out.println("myService = " + myService); + } +} +``` + +`MyService` 是一个简单的服务类,但我们没有定义任何方法或功能。 + +```java +@Service +public class MyService { + +} +``` + +运行结果发现,我们使用 `@Resource` 注解的功能,在我们的 Spring 上下文中工作正常,并且它成功地自动注入了所需的依赖关系。 + +```java +myService = com.xcs.spring.service.MyService@f0c8a99 +``` + +### 六、时序图 + +~~~mermaid +sequenceDiagram +Title: @Resource注解时序图 +AbstractAutowireCapableBeanFactory->>AbstractAutowireCapableBeanFactory:applyMergedBeanDefinitionPostProcessors(mbd,beanType,beanName)
应用Bean定义的后置处理器 +AbstractAutowireCapableBeanFactory->>CommonAnnotationBeanPostProcessor:postProcessMergedBeanDefinition(beanDefinition,beanType,beanName)
处理已合并的Bean定义 +CommonAnnotationBeanPostProcessor->>CommonAnnotationBeanPostProcessor:findResourceMetadata(beanName,clazz,pvs) +CommonAnnotationBeanPostProcessor->>CommonAnnotationBeanPostProcessor:buildResourceMetadata(clazz) +CommonAnnotationBeanPostProcessor->>ReflectionUtils:doWithLocalFields(clazz,fc)
处理类的本地字段 +ReflectionUtils->>CommonAnnotationBeanPostProcessor:解析有@Resource注解的字段 +CommonAnnotationBeanPostProcessor->>ResourceElement:ResourceElement(member,ae,pd) +CommonAnnotationBeanPostProcessor->>ReflectionUtils:doWithLocalMethods(clazz,fc)
处理类的本地方法 +ReflectionUtils->>CommonAnnotationBeanPostProcessor:解析有@Resource注解的方法 +CommonAnnotationBeanPostProcessor->>ResourceElement:ResourceElement(member,ae,pd) +CommonAnnotationBeanPostProcessor->>CommonAnnotationBeanPostProcessor:injectionMetadataCache.put(cacheKey, metadata)
将元数据存入缓存 +AbstractAutowireCapableBeanFactory->>AbstractAutowireCapableBeanFactory:populateBean(beanName,mbd,bw)
填充Bean的属性值 +AbstractAutowireCapableBeanFactory->>CommonAnnotationBeanPostProcessor:postProcessProperties(pvs,bean,beanName)
后处理Bean的属性 +CommonAnnotationBeanPostProcessor->>CommonAnnotationBeanPostProcessor:findResourceMetadata(beanName,clazz,pvs) +Note right of CommonAnnotationBeanPostProcessor:
从缓存中获取注入的元数据 +CommonAnnotationBeanPostProcessor->>InjectionMetadata:inject(target,beanName,pvs) +InjectionMetadata->>InjectedElement:inject(target,requestingBeanName,pvs) +InjectedElement->>ResourceElement:getResourceToInject(target,requestingBeanName) +ResourceElement->>CommonAnnotationBeanPostProcessor:getResource(element,requestingBeanName) +CommonAnnotationBeanPostProcessor->>CommonAnnotationBeanPostProcessor:autowireResource(factory,element,requestingBeanName) +CommonAnnotationBeanPostProcessor->>AbstractAutowireCapableBeanFactory:resolveBeanByName(name,descriptor) +AbstractAutowireCapableBeanFactory->>CommonAnnotationBeanPostProcessor:返回被依赖的Bean +CommonAnnotationBeanPostProcessor->>ResourceElement:返回被依赖的Bean +ResourceElement->>InjectedElement:返回被依赖的Bean +InjectedElement->>Field:field.set(target, 返回被依赖的Bean) +~~~ + +### 七、源码分析 + +### 八、注意事项 + +### 九、总结 + +#### 最佳实践总结 + +#### 源码分析总结 \ No newline at end of file diff --git a/spring-jsr/spring-jsr250-resource/pom.xml b/spring-jsr/spring-jsr250-resource/pom.xml index 6be0f62..db48926 100644 --- a/spring-jsr/spring-jsr250-resource/pom.xml +++ b/spring-jsr/spring-jsr250-resource/pom.xml @@ -7,13 +7,8 @@ com.xcs.spring 0.0.1-SNAPSHOT - 4.0.0 + 4.0.0 spring-jsr250-resource - - 11 - 11 - - \ No newline at end of file diff --git a/spring-jsr/spring-jsr250-resource/src/main/java/com/xcs/spring/ResourceApplication.java b/spring-jsr/spring-jsr250-resource/src/main/java/com/xcs/spring/ResourceApplication.java new file mode 100644 index 0000000..ad778d6 --- /dev/null +++ b/spring-jsr/spring-jsr250-resource/src/main/java/com/xcs/spring/ResourceApplication.java @@ -0,0 +1,18 @@ +package com.xcs.spring; + +import com.xcs.spring.config.MyConfiguration; +import com.xcs.spring.controller.MyController; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +/** + * @author xcs + * @date 2023年08月07日 16时21分 + **/ +public class ResourceApplication { + + public static void main(String[] args) { + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class); + MyController controller = context.getBean(MyController.class); + controller.showService(); + } +} diff --git a/spring-jsr/spring-jsr250-resource/src/main/java/com/xcs/spring/config/MyConfiguration.java b/spring-jsr/spring-jsr250-resource/src/main/java/com/xcs/spring/config/MyConfiguration.java new file mode 100644 index 0000000..a568737 --- /dev/null +++ b/spring-jsr/spring-jsr250-resource/src/main/java/com/xcs/spring/config/MyConfiguration.java @@ -0,0 +1,10 @@ +package com.xcs.spring.config; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan("com.xcs.spring") +public class MyConfiguration { + +} diff --git a/spring-jsr/spring-jsr250-resource/src/main/java/com/xcs/spring/controller/MyController.java b/spring-jsr/spring-jsr250-resource/src/main/java/com/xcs/spring/controller/MyController.java new file mode 100644 index 0000000..ad3bc01 --- /dev/null +++ b/spring-jsr/spring-jsr250-resource/src/main/java/com/xcs/spring/controller/MyController.java @@ -0,0 +1,18 @@ +package com.xcs.spring.controller; + +import com.xcs.spring.service.MyService; +import org.springframework.stereotype.Controller; + +import javax.annotation.Resource; +import javax.inject.Inject; + +@Controller +public class MyController { + + @Resource(name="myService") + private MyService myService; + + public void showService(){ + System.out.println("myService = " + myService); + } +} diff --git a/spring-jsr/spring-jsr250-resource/src/main/java/com/xcs/spring/service/MyService.java b/spring-jsr/spring-jsr250-resource/src/main/java/com/xcs/spring/service/MyService.java new file mode 100644 index 0000000..fdbde03 --- /dev/null +++ b/spring-jsr/spring-jsr250-resource/src/main/java/com/xcs/spring/service/MyService.java @@ -0,0 +1,7 @@ +package com.xcs.spring.service; + +import org.springframework.stereotype.Service; + +@Service +public class MyService { +}