Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
希川
container-mini
提交
7ca6c526
C
container-mini
项目概览
希川
/
container-mini
通知
6
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
container-mini
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
7ca6c526
编写于
11月 08, 2021
作者:
希川
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
<feat>: 自动扫描 Bean 对象
上级
a3ca3770
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
244 addition
and
37 deletion
+244
-37
pom.xml
pom.xml
+5
-0
src/main/java/cn/noexception/container/context/annotation/ClassPathBeanDefinitionScanner.java
...er/context/annotation/ClassPathBeanDefinitionScanner.java
+57
-0
src/main/java/cn/noexception/container/context/annotation/ClassPathScanningCandidateComponentProvider.java
...notation/ClassPathScanningCandidateComponentProvider.java
+26
-0
src/main/java/cn/noexception/container/context/annotation/Scope.java
...va/cn/noexception/container/context/annotation/Scope.java
+23
-0
src/main/java/cn/noexception/container/factory/PropertyPlaceholderConfigurer.java
...tion/container/factory/PropertyPlaceholderConfigurer.java
+66
-0
src/main/java/cn/noexception/container/factory/stereotype/Cube.java
...ava/cn/noexception/container/factory/stereotype/Cube.java
+17
-0
src/main/java/cn/noexception/container/factory/utils/ClassUtils.java
...va/cn/noexception/container/factory/utils/ClassUtils.java
+3
-0
src/main/java/cn/noexception/container/factory/xml/XmlBeanDefinitionReader.java
...eption/container/factory/xml/XmlBeanDefinitionReader.java
+47
-37
未找到文件。
pom.xml
浏览文件 @
7ca6c526
...
...
@@ -58,6 +58,11 @@
<artifactId>
hutool-all
</artifactId>
<version>
5.5.0
</version>
</dependency>
<dependency>
<groupId>
org.dom4j
</groupId>
<artifactId>
dom4j
</artifactId>
<version>
2.1.3
</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.openjdk.jol/jol-cli -->
<dependency>
<groupId>
org.openjdk.jol
</groupId>
...
...
src/main/java/cn/noexception/container/context/annotation/ClassPathBeanDefinitionScanner.java
0 → 100644
浏览文件 @
7ca6c526
package
cn.noexception.container.context.annotation
;
import
cn.hutool.core.util.StrUtil
;
import
cn.noexception.container.factory.config.BeanDefinition
;
import
cn.noexception.container.factory.stereotype.Cube
;
import
cn.noexception.container.factory.support.BeanDefinitionRegistry
;
import
java.util.Set
;
/**
* ClassPathBeanDefinitionScanner
*
* 扫描包处理
*
* @author 吕滔
* @Date 2021/11/8 17:21
*/
public
class
ClassPathBeanDefinitionScanner
extends
ClassPathScanningCandidateComponentProvider
{
private
BeanDefinitionRegistry
registry
;
public
ClassPathBeanDefinitionScanner
(
BeanDefinitionRegistry
registry
)
{
this
.
registry
=
registry
;
}
public
void
doScan
(
String
...
basePackages
)
{
for
(
String
basePackage
:
basePackages
)
{
Set
<
BeanDefinition
>
candidates
=
findCandidateComponents
(
basePackage
);
for
(
BeanDefinition
beanDefinition
:
candidates
)
{
// 解析 Bean 的作用域 singleton、prototype
String
beanScope
=
resolveBeanScope
(
beanDefinition
);
if
(
StrUtil
.
isNotEmpty
(
beanScope
))
{
beanDefinition
.
setScope
(
beanScope
);
}
registry
.
registerBeanDefinition
(
determineBeanName
(
beanDefinition
),
beanDefinition
);
}
}
}
private
String
determineBeanName
(
BeanDefinition
beanDefinition
)
{
Class
<?>
beanClass
=
beanDefinition
.
getBeanClass
();
Cube
cube
=
beanClass
.
getAnnotation
(
Cube
.
class
);
String
value
=
cube
.
value
();
if
(
StrUtil
.
isEmpty
(
value
))
{
value
=
StrUtil
.
lowerFirst
(
beanClass
.
getSimpleName
());
}
return
value
;
}
private
String
resolveBeanScope
(
BeanDefinition
beanDefinition
)
{
Class
<?>
beanClass
=
beanDefinition
.
getBeanClass
();
Scope
scope
=
beanClass
.
getAnnotation
(
Scope
.
class
);
if
(
null
!=
scope
)
return
scope
.
value
();
return
StrUtil
.
EMPTY
;
}
}
src/main/java/cn/noexception/container/context/annotation/ClassPathScanningCandidateComponentProvider.java
0 → 100644
浏览文件 @
7ca6c526
package
cn.noexception.container.context.annotation
;
import
cn.hutool.core.util.ClassUtil
;
import
cn.noexception.container.factory.config.BeanDefinition
;
import
cn.noexception.container.factory.stereotype.Cube
;
import
java.util.LinkedHashSet
;
import
java.util.Set
;
/**
* ClassPathScanningCandidateComponentProvider
*
* @author 吕滔
* @Date 2021/11/8 16:55
*/
public
class
ClassPathScanningCandidateComponentProvider
{
public
Set
<
BeanDefinition
>
findCandidateComponents
(
String
basePackage
){
Set
<
BeanDefinition
>
candidates
=
new
LinkedHashSet
<>();
Set
<
Class
<?>>
classes
=
ClassUtil
.
scanPackageByAnnotation
(
basePackage
,
Cube
.
class
);
for
(
Class
<?>
clazz
:
classes
)
{
candidates
.
add
(
new
BeanDefinition
(
clazz
));
}
return
candidates
;
}
}
src/main/java/cn/noexception/container/context/annotation/Scope.java
0 → 100644
浏览文件 @
7ca6c526
package
cn.noexception.container.context.annotation
;
import
java.lang.annotation.*
;
/**
* Scope
* 作用域注解
*
* @author 吕滔
* @Date 2021/11/8 16:40
*/
@Target
({
ElementType
.
TYPE
,
ElementType
.
METHOD
})
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Documented
public
@interface
Scope
{
/**
* 方便通过配置 Bean 对象注解的时候,拿到 Bean 对象的作用域。
*
* @return 默认使用 singleton
*/
String
value
()
default
"singleton"
;
}
src/main/java/cn/noexception/container/factory/PropertyPlaceholderConfigurer.java
0 → 100644
浏览文件 @
7ca6c526
package
cn.noexception.container.factory
;
import
cn.noexception.container.BeansException
;
import
cn.noexception.container.PropertyValue
;
import
cn.noexception.container.PropertyValues
;
import
cn.noexception.container.factory.config.BeanDefinition
;
import
cn.noexception.container.factory.config.BeanFactoryPostProcessor
;
import
cn.noexception.container.factory.io.DefaultResourceLoader
;
import
cn.noexception.container.factory.io.Resource
;
import
java.util.Properties
;
/**
* PropertyPlaceholderConfigurer
* 占位符配置
*
* @author 吕滔
* @Date 2021/11/8 16:14
*/
public
class
PropertyPlaceholderConfigurer
implements
BeanFactoryPostProcessor
{
private
static
final
String
DEFAULT_PLACEHOLDER_PREFIX
=
"${"
;
private
static
final
String
DEFAULT_PLACEHOLDER_SUFFIX
=
"}"
;
private
String
location
;
@Override
public
void
postProcessBeanFactory
(
ConfigurableListableBeanFactory
beanFactory
)
throws
BeansException
{
// 加载属性文件
try
{
DefaultResourceLoader
resourceLoader
=
new
DefaultResourceLoader
();
Resource
resource
=
resourceLoader
.
getResource
(
location
);
Properties
properties
=
new
Properties
();
properties
.
load
(
resource
.
getInputStream
());
// 占位符替换
String
[]
beanDefinitionNames
=
beanFactory
.
getBeanDefinitionNames
();
for
(
String
beanName
:
beanDefinitionNames
)
{
BeanDefinition
beanDefinition
=
beanFactory
.
getBeanDefinition
(
beanName
);
PropertyValues
propertyValues
=
beanDefinition
.
getPropertyValues
();
for
(
PropertyValue
propertyValue
:
propertyValues
.
getPropertyValues
())
{
Object
value
=
propertyValue
.
getValue
();
if
(!(
value
instanceof
String
))
continue
;
String
strVal
=
(
String
)
value
;
StringBuilder
buffer
=
new
StringBuilder
(
strVal
);
int
startIdx
=
strVal
.
indexOf
(
DEFAULT_PLACEHOLDER_PREFIX
);
int
stopIdx
=
strVal
.
indexOf
(
DEFAULT_PLACEHOLDER_SUFFIX
);
if
(
startIdx
!=
-
1
&&
stopIdx
!=
-
1
&&
startIdx
<
stopIdx
)
{
String
propKey
=
strVal
.
substring
(
startIdx
+
2
,
stopIdx
);
String
propVal
=
properties
.
getProperty
(
propKey
);
buffer
.
replace
(
startIdx
,
stopIdx
+
1
,
propVal
);
propertyValues
.
addPropertyValue
(
new
PropertyValue
(
propertyValue
.
getName
(),
buffer
.
toString
()));
}
}
}
}
catch
(
Exception
ex
){
throw
new
BeansException
(
" properties 加载失败"
,
ex
);
}
}
public
void
setLocation
(
String
location
)
{
this
.
location
=
location
;
}
}
src/main/java/cn/noexception/container/factory/stereotype/Cube.java
0 → 100644
浏览文件 @
7ca6c526
package
cn.noexception.container.factory.stereotype
;
import
java.lang.annotation.*
;
/**
* Cube
* 定义容器组件注解标记
*
* @author 吕滔
* @Date 2021/11/8 16:53
*/
@Target
(
ElementType
.
TYPE
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Documented
public
@interface
Cube
{
String
value
()
default
""
;
}
src/main/java/cn/noexception/container/factory/utils/ClassUtils.java
浏览文件 @
7ca6c526
package
cn.noexception.container.factory.utils
;
import
cn.noexception.container.ApplicationListener
;
import
cn.noexception.container.factory.stereotype.Cube
;
import
java.util.Set
;
/**
* ClassUtils
...
...
src/main/java/cn/noexception/container/factory/xml/XmlBeanDefinitionReader.java
浏览文件 @
7ca6c526
...
...
@@ -4,18 +4,21 @@ import cn.hutool.core.util.StrUtil;
import
cn.hutool.core.util.XmlUtil
;
import
cn.noexception.container.BeansException
;
import
cn.noexception.container.PropertyValue
;
import
cn.noexception.container.context.annotation.ClassPathBeanDefinitionScanner
;
import
cn.noexception.container.factory.config.BeanDefinition
;
import
cn.noexception.container.factory.config.BeanReference
;
import
cn.noexception.container.factory.io.Resource
;
import
cn.noexception.container.factory.io.ResourceLoader
;
import
cn.noexception.container.factory.support.AbstractBeanDefinitionReader
;
import
cn.noexception.container.factory.support.BeanDefinitionRegistry
;
import
org.w3c.dom.Document
;
import
org.w3c.dom.Element
;
import
org.w3c.dom.NodeList
;
import
org.dom4j.Document
;
import
org.dom4j.DocumentException
;
import
org.dom4j.Element
;
import
org.dom4j.io.SAXReader
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.util.List
;
/**
* XmlBeanDefinitionReader
...
...
@@ -38,7 +41,7 @@ public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
try
(
InputStream
inputStream
=
resource
.
getInputStream
())
{
doLoadBeanDefinition
(
inputStream
);
}
}
catch
(
IOException
|
ClassNotFoundException
e
)
{
}
catch
(
IOException
|
ClassNotFoundException
|
DocumentException
e
)
{
throw
new
BeansException
(
"IOException parsing XML document from "
+
resource
,
e
);
}
}
...
...
@@ -64,28 +67,32 @@ public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
}
}
private
void
doLoadBeanDefinition
(
InputStream
inputStream
)
throws
ClassNotFoundException
{
Document
doc
=
XmlUtil
.
readXML
(
inputStream
);
Element
root
=
doc
.
getDocumentElement
();
NodeList
childNodes
=
root
.
getChildNodes
();
for
(
int
i
=
0
;
i
<
childNodes
.
getLength
();
i
++)
{
// 判断元素
if
(!(
childNodes
.
item
(
i
)
instanceof
Element
))
continue
;
// 判断对象
if
(!
"bean"
.
equals
(
childNodes
.
item
(
i
).
getNodeName
()))
continue
;
// 解析标签
Element
bean
=
(
Element
)
childNodes
.
item
(
i
);
String
id
=
bean
.
getAttribute
(
"id"
);
String
name
=
bean
.
getAttribute
(
"name"
);
String
className
=
bean
.
getAttribute
(
"class"
);
String
initMethod
=
bean
.
getAttribute
(
"init-method"
);
String
destroyMethodName
=
bean
.
getAttribute
(
"destroy-method"
);
private
void
doLoadBeanDefinition
(
InputStream
inputStream
)
throws
ClassNotFoundException
,
DocumentException
{
SAXReader
reader
=
new
SAXReader
();
Document
doc
=
reader
.
read
(
inputStream
);
Element
root
=
doc
.
getRootElement
();
// 解析 context:component-scan 标签, 扫描包中的类并提取相关信息,用于组装 BeanDefinition
Element
componentScan
=
root
.
element
(
"component-scan"
);
if
(
null
!=
componentScan
)
{
String
scanPath
=
componentScan
.
attributeValue
(
"base-package"
);
if
(
StrUtil
.
isEmpty
(
scanPath
))
{
throw
new
BeansException
(
"base-package 为空。"
);
}
scanPackage
(
scanPath
);
}
List
<
Element
>
beanList
=
root
.
elements
(
"bean"
);
for
(
Element
bean
:
beanList
)
{
String
id
=
bean
.
attributeValue
(
"id"
);
String
name
=
bean
.
attributeValue
(
"name"
);
String
className
=
bean
.
attributeValue
(
"class"
);
String
initMethod
=
bean
.
attributeValue
(
"init-method"
);
String
destroyMethodName
=
bean
.
attributeValue
(
"destroy-method"
);
// 增加了关于 Bean 对象配置中 scope 的解析,并把这个属性信息填充到 Bean 定义中
String
beanScope
=
bean
.
getAttribut
e
(
"scope"
);
String
beanScope
=
bean
.
attributeValu
e
(
"scope"
);
// 获取 Class,方便获取类中的名称
Class
<?>
clazz
=
Class
.
forName
(
className
);
...
...
@@ -102,29 +109,32 @@ public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
if
(
StrUtil
.
isNotEmpty
(
beanScope
))
{
beanDefinition
.
setScope
(
beanScope
);
}
List
<
Element
>
propertyList
=
bean
.
elements
(
"property"
);
// 读取属性并填充
for
(
int
j
=
0
;
j
<
bean
.
getChildNodes
().
getLength
();
j
++)
{
if
(!(
bean
.
getChildNodes
().
item
(
j
)
instanceof
Element
))
continue
;
if
(!
"property"
.
equals
(
bean
.
getChildNodes
().
item
(
j
).
getNodeName
()))
continue
;
// 解析标签 property
Element
property
=
(
Element
)
bean
.
getChildNodes
().
item
(
j
);
String
attrName
=
property
.
getAttribute
(
"name"
);
String
attrValue
=
property
.
getAttribute
(
"value"
);
String
attrRef
=
property
.
getAttribute
(
"ref"
);
for
(
Element
property
:
propertyList
)
{
String
attrName
=
property
.
attributeValue
(
"name"
);
String
attrValue
=
property
.
attributeValue
(
"value"
);
String
attrRef
=
property
.
attributeValue
(
"ref"
);
// 获取属性值:引入对象、值对象
Object
value
=
StrUtil
.
isNotEmpty
(
attrRef
)
?
new
BeanReference
(
attrRef
):
attrValue
;
Object
value
=
StrUtil
.
isNotEmpty
(
attrRef
)
?
new
BeanReference
(
attrRef
)
:
attrValue
;
// 创建属性信息
PropertyValue
propertyValue
=
new
PropertyValue
(
attrName
,
value
);
beanDefinition
.
getPropertyValues
().
addPropertyValue
(
propertyValue
);
}
if
(
getRegistry
().
containsBeanDefinition
(
beanName
))
{
throw
new
BeansException
(
"Duplicate beanName["
+
beanName
+
"] is not allowed"
);
throw
new
BeansException
(
"Duplicate beanName["
+
beanName
+
"] is not allowed"
);
}
// 注册 BeanDefinition
getRegistry
().
registerBeanDefinition
(
beanName
,
beanDefinition
);
}
}
private
void
scanPackage
(
String
scanPath
)
{
String
[]
basesPackages
=
StrUtil
.
splitToArray
(
scanPath
,
','
);
ClassPathBeanDefinitionScanner
scanner
=
new
ClassPathBeanDefinitionScanner
(
getRegistry
());
scanner
.
doScan
(
basesPackages
);
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录