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.<init>:构造实例对象
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.<init>(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<Class<? extends Annotation>> resourceAnnotationTypes = new LinkedHashSet(4);
//资源注入类注解
@Nullable
private static final Class<? extends Annotation> webServiceRefClass;
@Nullable
private static final Class<? extends Annotation> ejbClass;
private final Set<String> 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<String, InjectionMetadata> 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
???????
????????????????
|