spring @Resource原理及自定义实现

spring @Resource原理及自定义实现,第1张


spring @Resource原理及自定义实现

           

                    

                                       

@Resource 原理

           

@Resource注解通过CommonAnnotationBeanPostProcessor来实现属性注入

                         

          

HelloService

public interface HelloService {

    String hello();
}

         

HelloServiceImpl

@Service
public class HelloServiceImpl implements HelloService {

    @Override
    public String hello() {
        return "hello";
    }
}

          

HelloController

@RestController
public class HelloController {

    @Resource
    private HelloService helloService;

    @RequestMapping("/hello")
    public String hello(){
        return helloService.hello();
    }
}

       

CommonAnnotationBeanPostProcessor实例化调用栈

# CommonAnnotationBeanPostProcessor.:构造实例对象
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.(CommonAnnotationBeanPostProcessor.java:204)
	  at sun.reflect.NativeConstructorAccessorImpl.newInstance0(NativeConstructorAccessorImpl.java:-1)
	  at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	  at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	  at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	  at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:211)

# SimpleInstantiationStrategy类
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87)

# AbstractAutowireCapableBeanFactory类
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1326)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1232)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)

# AbstractBeanFactory类
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$205.1751403001.getObject(Unknown Source:-1)

# DefaultSingletonBeanRegistry类
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	  - locked <0xfac> (a java.util.concurrent.ConcurrentHashMap)

# AbstractBeanFactory类
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:213)

# PostProcessorRegistrationDelegate类
at org.springframework.context.support.PostProcessorRegistrationDelegate.registerBeanPostProcessors(PostProcessorRegistrationDelegate.java:237)

# AbstractApplicationContext类
at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:762)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:567)
	  - locked <0xfad> (a java.lang.Object)

# ServletWebServerApplicationContext类
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)

# SpringApplication类
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:740)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:415)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301)

# 项目启动入口
at com.example.demo.DemoApplication.main(DemoApplication.java:10)

         

属性注入调用栈

# CommonAnnotationBeanPostProcessor.postProcessProperties:属性注入
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:329)

# AbstractAutowireCapableBeanFactory类
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)

# AbstractBeanFactory类
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$208.882471736.getObject(Unknown Source:-1)

# DefaultSingletonBeanRegistry类
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	  - locked <0x13a3> (a java.util.concurrent.ConcurrentHashMap)

# AbstractBeanFactory类
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)

# DefaultListableBeanFactory类
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:953)

# AbstractApplicationContext类
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
	  - locked <0x13a4> (a java.lang.Object)

# ServletWebServerApplicationContext类
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)

# SpringApplication类
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:740)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:415)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301)

# 项目启动入口
at com.example.demo.DemoApplication.main(DemoApplication.java:10)

            

CommonAnnotationBeanPostProcessor

public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor, BeanFactoryAware, Serializable {
    private static final boolean jndiPresent = ClassUtils.isPresent("javax.naming.InitialContext", CommonAnnotationBeanPostProcessor.class.getClassLoader());
    private static final Set> resourceAnnotationTypes = new LinkedHashSet(4);
                                                          //资源注入类注解
    @Nullable
    private static final Class webServiceRefClass;
    @Nullable
    private static final Class ejbClass;
    private final Set ignoredResourceTypes = new HashSet(1);
    private boolean fallbackToDefaultTypeMatch = true;
    private boolean alwaysUseJndiLookup = false;
    @Nullable
    private transient BeanFactory jndiFactory;
    @Nullable
    private transient BeanFactory resourceFactory;
    @Nullable
    private transient BeanFactory beanFactory;
    @Nullable
    private transient StringValueResolver embeddedValueResolver;
    private final transient Map injectionMetadataCache = new ConcurrentHashMap(256);

    public CommonAnnotationBeanPostProcessor() {
        this.setOrder(2147483644);
        this.setInitAnnotationType(PostConstruct.class);    //处理PostConstruct注解
        this.setDestroyAnnotationType(PreDestroy.class);    //处理PreDestroy注解
        this.ignoreResourceType("javax.xml.ws.WebServiceContext");
        if (jndiPresent) {
            this.jndiFactory = new SimpleJndiBeanFactory();
        }

    }


    static {
        resourceAnnotationTypes.add(Resource.class);    //资源注入类注解:@Resource
        webServiceRefClass = loadAnnotationType("javax.xml.ws.WebServiceRef");
        if (webServiceRefClass != null) {
            resourceAnnotationTypes.add(webServiceRefClass);
        }

        ejbClass = loadAnnotationType("javax.ejb.EJB");
        if (ejbClass != null) {
            resourceAnnotationTypes.add(ejbClass);
        }

    }

    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
                          //属性注入
        InjectionMetadata metadata = this.findResourceMetadata(beanName, bean.getClass(), pvs);

        try {
            metadata.inject(bean, beanName, pvs);     //注入属性
            return pvs;
        } catch (Throwable var6) {
            throw new BeanCreationException(beanName, "Injection of resource dependencies failed", var6);
        }
    }


*********
内部类:ResourceElement

    private class ResourceElement extends CommonAnnotationBeanPostProcessor.LookupElement {
        private final boolean lazyLookup;

        public ResourceElement(Member member, AnnotatedElement ae, @Nullable PropertyDescriptor pd) {
            super(member, pd);
            Resource resource = (Resource)ae.getAnnotation(Resource.class);
            String resourceName = resource.name();
            Class resourceType = resource.type();
            this.isDefaultName = !StringUtils.hasLength(resourceName);
            if (this.isDefaultName) {
                resourceName = this.member.getName();
                if (this.member instanceof Method && resourceName.startsWith("set") && resourceName.length() > 3) {
                    resourceName = Introspector.decapitalize(resourceName.substring(3));
                }
            } else if (CommonAnnotationBeanPostProcessor.this.embeddedValueResolver != null) {
                resourceName = CommonAnnotationBeanPostProcessor.this.embeddedValueResolver.resolveStringValue(resourceName);
            }

            if (Object.class != resourceType) {
                this.checkResourceType(resourceType);
            } else {
                resourceType = this.getResourceType();
            }

            this.name = resourceName != null ? resourceName : "";
            this.lookupType = resourceType;
            String lookupValue = resource.lookup();
            this.mappedName = StringUtils.hasLength(lookupValue) ? lookupValue : resource.mappedName();
            Lazy lazy = (Lazy)ae.getAnnotation(Lazy.class);
            this.lazyLookup = lazy != null && lazy.value();
        }

        protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {
                         //获取要注入的对象
            return this.lazyLookup ? CommonAnnotationBeanPostProcessor.this.buildLazyResourceProxy(this, requestingBeanName) : CommonAnnotationBeanPostProcessor.this.getResource(this, requestingBeanName);
        }
    }

        

                 

                                       

自定义实现

       

                         

        

CustomResource

@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomResource {

    String name() default "";
    Class type() default Object.class;
}

         

HelloService

public interface HelloService {

    String hello();
}

      

HelloServiceImpl

@Service
public class HelloServiceImpl implements HelloService {

    @Override
    public String hello() {
        return "hello";
    }
}

        

HelloController

@RestController
public class HelloController {

    @CustomResource
    private HelloService helloService;

    @RequestMapping("/hello")
    public String hello(){
        System.out.println(helloService.hello());

        return "hello";
    }
}

      

localhost:8080/hello:点击运行,控制台输出

2022-04-27 10:19:40.416  INFO 1266 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-04-27 10:19:40.417  INFO 1266 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 762 ms
2022-04-27 10:19:40.682  INFO 1266 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2022-04-27 10:19:40.691  INFO 1266 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 1.588 seconds (JVM running for 2.161)
2022-04-27 10:19:43.979  INFO 1266 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2022-04-27 10:19:43.980  INFO 1266 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2022-04-27 10:19:43.980  INFO 1266 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 0 ms
hello

       

                

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/759225.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-01
下一篇 2022-05-01

发表评论

登录后才能评论

评论列表(0条)

保存