之前主要都是通过配置文件定义spring的一些bean,以及一些属性文件, 不过后面spring升级成springboot后,很多都开始用注解开发来取代配置文件了.
所以我们也开始慢慢升级了.
第一步先来两个常见注解
@Component只要使用了@interface就能在class中被扫描到,这个我们后面再说.
package com.linnine.spring.stereotype;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Component {
//组件名
String value() default "";
}
@Scope
package com.linnine.spring.context.annotation;
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Scope {
//默认单例
String value() default "singleton";
}
ClassPathScanningCandidateComponentProvider
这个类主要用于扫描注定包目录下所有带@Component注解的类
package com.linnine.spring.context.annotation;
public class ClassPathScanningCandidateComponentProvider {
public Set findCandidateComponents(String basePackage){
Set candidates = new LinkedHashSet<>();
//有用component主键的都加进去
Set> classes = ClassUtil.scanPackageByAnnotation(basePackage, Component.class);
for (Class> aClass : classes) {
candidates.add(new BeanDefinition(aClass));
}
return candidates;
}
}
ClassPathBeanDefinitionScanner
然后开始对这些类进行处理 这里是获取所有组件类定义作用域后注册
package com.linnine.spring.context.annotation;
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider{
private BeanDefinitionRegistry registry;
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
this.registry = registry;
}
public void doScan(String... basePackages){
for (String basePackage : basePackages) {
//获取带有@component注解的类
Set candidates = findCandidateComponents(basePackage);
for (BeanDefinition beanDefinition : candidates) {
//解析bean的作用域
String beanScope = resolveBeanScope(beanDefinition);
//如果有作用域
if (StrUtil.isNotEmpty(beanScope)){
beanDefinition.setScope(beanScope);
}
//通过bean定义获取组件名 并注册
registry.registerBeanDefinition(determineBeanName(beanDefinition),beanDefinition);
}
}
}
private String resolveBeanScope(BeanDefinition beanDefinition) {
Class> beanClass = beanDefinition.getBeanClass();
//获取这个类中的注解
Scope scope = beanClass.getAnnotation(Scope.class);
return null != scope ?scope.value():StrUtil.EMPTY;
}
private String determineBeanName(BeanDefinition beanDefinition) {
Class> beanClass = beanDefinition.getBeanClass();
// 获取组件信息
Component component = beanClass.getAnnotation(Component.class);
String value = component.value();
//判断是否有组件名
if (StrUtil.isEmpty(value)){
//没有就取类名 变将首字母小写
value = StrUtil.lowerFirst(beanClass.getSimpleName());
}
return value;
}
}
XmlBeanDefinitionReader
然后就是把这个扫描加入到xml的扫描过程中调用
先引入个依赖, 因为xml解析的流程也被改了
org.dom4j dom4j2.1.3
改造里面的方法,并添加了调用
protected void doLoadBeanDefinitions(InputStream inputStream) throws ClassNotFoundException, DocumentException {
SAXReader reader = new SAXReader();
Document document = reader.read(inputStream);
Element root = document.getRootElement();
Element componentScan = root.element("component-scan");
if (null != componentScan){
String scanPath = componentScan.attributeValue("base-package");
if (StrUtil.isEmpty(scanPath)){
throw new BeansException("The value of base-package attribute can not be empty or null");
}
scanPackage(scanPath);
}
List 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");
String beanScope = bean.attributeValue("scope");
// 获取 Class,方便获取类中的名称
Class> clazz = Class.forName(className);
// 优先级 id > name
String beanName = StrUtil.isNotEmpty(id) ? id : name;
if (StrUtil.isEmpty(beanName)) {
beanName = StrUtil.lowerFirst(clazz.getSimpleName());
}
// 定义Bean
BeanDefinition beanDefinition = new BeanDefinition(clazz);
beanDefinition.setInitMethodName(initMethod);
beanDefinition.setDestroyMethodName(destroyMethodName);
if (StrUtil.isNotEmpty(beanScope)) {
beanDefinition.setScope(beanScope);
}
List propertyList = bean.elements("property");
// 读取属性并填充
for (Element property : propertyList) {
// 解析标签:property
String attrName = property.attributeValue("name");
String attrValue = property.attributeValue("value");
String attrRef = property.attributeValue("ref");
// 获取属性值:引入对象、值对象
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");
}
// 注册 BeanDefinition
getRegistry().registerBeanDefinition(beanName, beanDefinition);
}
}
private void scanPackage(String scanPath) {
String[] basePackages = StrUtil.splitToArray(scanPath, ',');
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(getRegistry());
scanner.doScan(basePackages);
}
PropertyPlaceholderConfigurer
标题上的属性注入也搞一下, 后面应该是用@Value来替代
package com.linnine.spring.beans.factory;
@Data
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 postProcessorBeanFactory(ConfigurableListableBeanFactory beanFactory) {
//加载属性文件
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
Resource resource = resourceLoader.getResource(location);
Properties properties = new Properties();
try {
//加载配置信息
properties.load(resource.getInputStream());
//获取所有bean定义名
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 builder = new StringBuilder(strVal);
//判断 属性值 value="${value}" 是否有使用占位符
int startIdx = strVal.indexOf(DEFAULT_PLACEHOLDER_PREFIX);
int stopIdx = strVal.indexOf(DEFAULT_PLACEHOLDER_SUFFIX);
//如果使用了占位符
if (startIdx!=-1 && stopIdx !=-1 && startIdx
UserService
加上注解和一条属性用来测试属性注入
补充一下token的相关方法
@Override
public String toString() {
return "UserService#token = { " + token + " }";
}
配置文件
spring-property.xml
配置上面的属性注入类
热门相关搜索
路由器设置
木托盘
宝塔面板
儿童python教程
心情低落
朋友圈
vim
双一流学科
专升本
我的学校
日记学校
西点培训学校
汽修学校
情书
化妆学校
塔沟武校
异形模板
西南大学排名
最精辟人生短句
6步教你追回被骗的钱
南昌大学排名
清朝十二帝
北京印刷学院排名
北方工业大学排名
北京航空航天大学排名
首都经济贸易大学排名
中国传媒大学排名
首都师范大学排名
中国地质大学(北京)排名
北京信息科技大学排名
中央民族大学排名
北京舞蹈学院排名
北京电影学院排名
中国戏曲学院排名
河北政法职业学院排名
河北经贸大学排名
天津中德应用技术大学排名
天津医学高等专科学校排名
天津美术学院排名
天津音乐学院排名
天津工业大学排名
北京工业大学耿丹学院排名
北京警察学院排名
天津科技大学排名
北京邮电大学(宏福校区)排名
北京网络职业学院排名
北京大学医学部排名
河北科技大学排名
河北地质大学排名
河北体育学院排名



