Spring编程模型
1、面向对象编程,包含的特性有:
契约接口:Aware,BeanPostProcessor(Bean初始化前后回调函数)
设计模式:观察者模式、组合模式、模板模式
Aware接口对应回调模式,Spring3.1引入,如子接口ApplicationContextAware:
public interface ApplicationContextAware extends Aware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
就可以完成对ApplicationContext的回调获取
监视器模式,具体实现就是Spring的事件发布
我们使用的时候只需要使用Publisher来多拨事件,通过ApplicationListener来捕获事件即可
其实Publisher内部调用了ApplicationEventMulticaster的multicastEvent方法,内部是通过ApplicationEventMulticaster这个多播器来实现的。
组合模式,例子为CompositeCacheManager
public class CompositeCacheManager implements CacheManager, InitializingBean {
private final List<CacheManager> cacheManagers = new ArrayList<>();
}
该类实现了CacheManager同时内部也持有CacheManager的列表完成缓存合并
模板模式,JdbcTemplate
2、面向切面编程
动态代理:AopProxy
字节码提升:ASM(类似于汇编语言层面的提升)、CGLIB(动态字节码生成技术)、AspectJ
动态代理AopProxy有几个实现类:
JdkDynamicAopProxy——>CglibAopProxy
越来越底层
3、面向元编程
注解:模式注解(@Component、@Controller、@Service、@Repository)
配置:Environment底层抽象、PropertySources、BeanDefinition
泛型:ResolvableType泛型处理
因为Java注解是不能实现派生的,所以需要在注解上面进行重复标注
如在@Controller和@Service上面就需要标注上@Component注解来实现元注解标注
如Environment就可以获取到Profile,实现在不同Profile下的不同配置信息
4、面向函数
主要提供的@FunctionalInterface接口和WebFlux环境
5、面向模块
主要是@Enable*注解
Spring IoC基础
大量使用到了Java Bean,在1.1的时候引入,类似于反射,但是比Java的反射好用的太多
使用示例(输出当前Bean所有的方法(构造器方法除外,即使是显式构造器也不会出现在输出当中)):
public static void main(String[] args) throws IntrospectionException {
BeanInfo beanInfo = Introspector.getBeanInfo(Person.class, Object.class);
Arrays.stream(beanInfo.getMethodDescriptors()).forEach(System.out::println);
}
输出:
java.beans.MethodDescriptor[name=getName; method=public java.lang.String cn.luckycurve.beans.Person.getName()]
java.beans.MethodDescriptor[name=setAge; method=public void cn.luckycurve.beans.Person.setAge(java.lang.Integer)]
java.beans.MethodDescriptor[name=setName; method=public void cn.luckycurve.beans.Person.setName(java.lang.String)]
java.beans.MethodDescriptor[name=getAge; method=public java.lang.Integer cn.luckycurve.beans.Person.getAge()]
核心方法是:public static BeanInfo getBeanInfo(Class<?> beanClass, Class<?> stopClass) throws IntrospectionException
如果不使用stopClass则会直接输出所有的类,使用stopClass则会屏蔽掉stopClass中的方法,只显示当前层级的方法。
通过BeanInfo还可以获取到PropertyDescriptor,Spring通过PropertyEditor来将Text转换成为相应的数据类型:
public static void main(String[] args) throws IntrospectionException {
BeanInfo beanInfo = Introspector.getBeanInfo(Person.class, Object.class);
Arrays.stream(beanInfo.getPropertyDescriptors()).forEach(propertyDescriptor -> {
String propertyDescriptorName = propertyDescriptor.getName();
if (Objects.equals("age", propertyDescriptorName)) {
propertyDescriptor.setPropertyEditorClass(StringToIntegerPropertyEditor.class);
}
});
}
static class StringToIntegerPropertyEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
Integer value = Integer.valueOf(text);
setValue(value);
}
}