Skip to content

Commit b7e2e32

Browse files
committed
spring官方注入bean的套路
1 parent b0dc0b0 commit b7e2e32

13 files changed

+356
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
- registerbean包下的所有类,均是拷贝的李佳明的代码
2+
- 详细github地址
3+
- https://github.com/pkpk1234/registerbean-ImportBeanDefinitionRegistrar
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.zz.spring.registerbean;
2+
3+
import com.zz.spring.registerbean.annotation.EnableHttpUtil;
4+
import org.springframework.boot.SpringApplication;
5+
import org.springframework.boot.autoconfigure.SpringBootApplication;
6+
7+
/**
8+
* @author 李佳明
9+
* @date 2017.10.14
10+
*/
11+
@SpringBootApplication
12+
@EnableHttpUtil
13+
public class RegisterbeanImportBeanDefinitionRegistrarApplication {
14+
15+
public static void main(String[] args) {
16+
SpringApplication.run(RegisterbeanImportBeanDefinitionRegistrarApplication.class, args);
17+
}
18+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.zz.spring.registerbean.annotation;
2+
3+
import com.zz.spring.registerbean.http.HTTPRequestRegistrar;
4+
import org.springframework.context.annotation.Import;
5+
6+
import java.lang.annotation.ElementType;
7+
import java.lang.annotation.Retention;
8+
import java.lang.annotation.RetentionPolicy;
9+
import java.lang.annotation.Target;
10+
11+
/**
12+
* @author 李佳明
13+
* @date 2017.10.14
14+
*
15+
*/
16+
@Retention(RetentionPolicy.RUNTIME)
17+
@Target(ElementType.TYPE)
18+
@Import(HTTPRequestRegistrar.class)
19+
public @interface EnableHttpUtil {
20+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.zz.spring.registerbean.annotation;
2+
3+
/**
4+
* @author 李佳明
5+
* @date 2017.10.14
6+
*/
7+
public enum HTTPMethod {
8+
GET,POST,PUT,DELETE
9+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.zz.spring.registerbean.annotation;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
/**
9+
* @author 李佳明
10+
* @date 2017.10.14
11+
*
12+
*/
13+
@Retention(RetentionPolicy.RUNTIME)
14+
@Target(ElementType.METHOD)
15+
public @interface HTTPRequest {
16+
HTTPMethod httpMethod() default HTTPMethod.GET;
17+
String url();
18+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.zz.spring.registerbean.annotation;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
/**
9+
* @author 李佳明
10+
* @date 2017.10.14
11+
*/
12+
@Retention(RetentionPolicy.RUNTIME)
13+
@Target(ElementType.TYPE)
14+
public @interface HTTPUtil {
15+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.zz.spring.registerbean.controller;
2+
3+
import com.zz.spring.registerbean.itface.IRequestDemo;
4+
import com.zz.spring.registerbean.http.HttpResult;
5+
import org.springframework.beans.factory.annotation.Autowired;
6+
import org.springframework.web.bind.annotation.RequestMapping;
7+
import org.springframework.web.bind.annotation.RestController;
8+
9+
/**
10+
* @Author: zengzhen
11+
* @Date: 2019/7/17 14:20
12+
* @Version 1.0
13+
*/
14+
@RestController
15+
public class HelloController {
16+
17+
@Autowired
18+
IRequestDemo requestDemo;
19+
@RequestMapping("/test1")
20+
public HttpResult<String> test1()
21+
{
22+
return requestDemo.test1();
23+
}
24+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.zz.spring.registerbean.http;
2+
3+
import com.zz.spring.registerbean.annotation.HTTPRequest;
4+
5+
import java.lang.reflect.Method;
6+
7+
/**
8+
* @author 李佳明
9+
* @date 2017.10.14
10+
*/
11+
public class DemoHttpHandler implements HTTPHandler {
12+
13+
@Override
14+
public HttpResult<?> handle(Method method) {
15+
HTTPRequest request = method.getAnnotation(HTTPRequest.class);
16+
String url = request.url();
17+
String methodName = request.httpMethod().name();
18+
String str = String.format("http request: url=%s and method=%s", url, methodName);
19+
return new StringHttpResult(str, 200);
20+
}
21+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.zz.spring.registerbean.http;
2+
3+
import java.lang.reflect.Method;
4+
5+
/**
6+
* @author 李佳明
7+
* @date 2017.10.14
8+
*/
9+
public interface HTTPHandler {
10+
HttpResult<?> handle(Method method);
11+
}
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
package com.zz.spring.registerbean.http;
2+
3+
import com.zz.spring.registerbean.annotation.HTTPRequest;
4+
import com.zz.spring.registerbean.annotation.HTTPUtil;
5+
import lombok.extern.slf4j.Slf4j;
6+
import org.springframework.beans.BeansException;
7+
import org.springframework.beans.factory.BeanClassLoaderAware;
8+
import org.springframework.beans.factory.BeanFactory;
9+
import org.springframework.beans.factory.BeanFactoryAware;
10+
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
11+
import org.springframework.beans.factory.config.BeanDefinition;
12+
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
13+
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
14+
import org.springframework.context.EnvironmentAware;
15+
import org.springframework.context.ResourceLoaderAware;
16+
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
17+
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
18+
import org.springframework.core.env.Environment;
19+
import org.springframework.core.io.ResourceLoader;
20+
import org.springframework.core.type.AnnotationMetadata;
21+
import org.springframework.core.type.filter.AnnotationTypeFilter;
22+
import org.springframework.util.ClassUtils;
23+
24+
import java.lang.reflect.InvocationHandler;
25+
import java.lang.reflect.Method;
26+
import java.lang.reflect.Proxy;
27+
import java.util.Set;
28+
29+
/**
30+
* @author 李佳明
31+
* @date 2017.10.14
32+
* 用于动态注册HTTPUtil接口的实现类
33+
*/
34+
@Slf4j
35+
public class HTTPRequestRegistrar implements ImportBeanDefinitionRegistrar,
36+
ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware, BeanFactoryAware {
37+
38+
private ClassLoader classLoader;
39+
private ResourceLoader resourceLoader;
40+
private Environment environment;
41+
private BeanFactory beanFactory;
42+
43+
@Override
44+
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
45+
registerHttpRequest(beanDefinitionRegistry);
46+
}
47+
48+
/**
49+
* 注册动态bean的主要方法
50+
*
51+
* @param beanDefinitionRegistry
52+
*/
53+
private void registerHttpRequest(BeanDefinitionRegistry beanDefinitionRegistry) {
54+
ClassPathScanningCandidateComponentProvider classScanner = getClassScanner();
55+
classScanner.setResourceLoader(this.resourceLoader);
56+
//指定只关注标注了@HTTPUtil注解的接口
57+
AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(HTTPUtil.class);
58+
classScanner.addIncludeFilter(annotationTypeFilter);
59+
//指定扫描的基础包
60+
String basePack = "com.zz.spring.registerbean.itface";
61+
Set<BeanDefinition> beanDefinitionSet = classScanner.findCandidateComponents(basePack);
62+
for (BeanDefinition beanDefinition : beanDefinitionSet) {
63+
if (beanDefinition instanceof AnnotatedBeanDefinition) {
64+
registerBeans(((AnnotatedBeanDefinition) beanDefinition));
65+
}
66+
}
67+
}
68+
69+
/**
70+
* 创建动态代理,并动态注册到容器中
71+
*
72+
* @param annotatedBeanDefinition
73+
*/
74+
private void registerBeans(AnnotatedBeanDefinition annotatedBeanDefinition) {
75+
String className = annotatedBeanDefinition.getBeanClassName();
76+
((DefaultListableBeanFactory) this.beanFactory).registerSingleton(className, createProxy(annotatedBeanDefinition));
77+
}
78+
79+
/**
80+
* 构造Class扫描器,设置了只扫描顶级接口,不扫描内部类
81+
*
82+
* @return
83+
*/
84+
private ClassPathScanningCandidateComponentProvider getClassScanner() {
85+
return new ClassPathScanningCandidateComponentProvider(false, this.environment) {
86+
87+
@Override
88+
protected boolean isCandidateComponent(
89+
AnnotatedBeanDefinition beanDefinition) {
90+
if (beanDefinition.getMetadata().isInterface()) {
91+
try {
92+
Class<?> target = ClassUtils.forName(
93+
beanDefinition.getMetadata().getClassName(),
94+
classLoader);
95+
return !target.isAnnotation();
96+
} catch (Exception ex) {
97+
log.error("load class exception:", ex);
98+
}
99+
}
100+
return false;
101+
}
102+
};
103+
}
104+
105+
/**
106+
* 创建动态代理
107+
*
108+
* @param annotatedBeanDefinition
109+
* @return
110+
*/
111+
private Object createProxy(AnnotatedBeanDefinition annotatedBeanDefinition) {
112+
try {
113+
AnnotationMetadata annotationMetadata = annotatedBeanDefinition.getMetadata();
114+
Class<?> target = Class.forName(annotationMetadata.getClassName());
115+
InvocationHandler invocationHandler = createInvocationHandler();
116+
Object proxy = Proxy.newProxyInstance(HTTPRequest.class.getClassLoader(), new Class[]{target}, invocationHandler);
117+
return proxy;
118+
} catch (ClassNotFoundException e) {
119+
log.error(e.getMessage());
120+
}
121+
return null;
122+
}
123+
124+
/**
125+
* 创建InvocationHandler,将方法调用全部代理给DemoHttpHandler
126+
*
127+
* @return
128+
*/
129+
private InvocationHandler createInvocationHandler() {
130+
return new InvocationHandler() {
131+
private DemoHttpHandler demoHttpHandler = new DemoHttpHandler();
132+
133+
@Override
134+
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
135+
136+
return demoHttpHandler.handle(method);
137+
}
138+
};
139+
}
140+
141+
@Override
142+
public void setBeanClassLoader(ClassLoader classLoader) {
143+
this.classLoader = classLoader;
144+
}
145+
146+
@Override
147+
public void setResourceLoader(ResourceLoader resourceLoader) {
148+
this.resourceLoader = resourceLoader;
149+
}
150+
151+
@Override
152+
public void setEnvironment(Environment environment) {
153+
this.environment = environment;
154+
}
155+
156+
@Override
157+
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
158+
this.beanFactory = beanFactory;
159+
}
160+
}

0 commit comments

Comments
 (0)