Spring编程思想

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);
    }
}

最后更新于