Spring核心编程思想(五)Spring 特性总览之Spring 编程模型

本文是小马克课程笔记,介绍了Spring对Java EE API的整合,涉及Web、数据存储、Bean技术等方面。还阐述了Spring编程模型,包括面向对象(契约接口、设计模式、对象继承)、面向切面(动态代理、字节码提升)、面向元编程(注解、配置、泛型)和函数驱动(函数接口、Reactive、模块驱动)等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

小马克课程笔记

Spring 对 Java EE API 整合

  • Java EE Web 技术相关
JSR 规范Spring 支持版本代表实现
Servlet + JSP(JSR 035)1.0 +DispatcherServlet
JSTL(JSR 052)1.0 +JstlView
JavaServer Faces(JSR 127)1.1 +FacesContextUtils
Portlet(JSR 168)2.0 - 4.2DispatcherPortlet
SOAP(JSR 067)2.5 +SoapFaultException
WebServices(JSR 109)2.5 +CommonAnnotationBeanPostProcessor
WebSocket(JSR 356)4.0 +WebSocketHandler
  • Java EE 数据存储相关
JSR 规范Spring 支持版本代表实现
JDO(JSR 12)1.0 - 4.2JdoTemplate
JTA(JSR 907)1.0 +JtaTransactionManager
JPA(EJB 3.0 JSR 220的成员)2.0 +JpaTransactionManager
Java Caching API(JSR 107)3.2 +JCacheCache
  • Java EE Bean 技术相关
JSR 规范Spring 支持版本代表实现
JMS(JSR 914)1.1 + JmsTemplate
EJB 2.0 (JSR 19)1.0 + AbstractStatefulSessionBean
Dependency Injection for Java(JSR 330)2.5 +AutowiredAnnotationBeanPostProcessor
Bean Validation(JSR 303)3.0 +LocalValidatorFactoryBean

Spring 编程模型

在这里插入图片描述

面向对象

契约接口

  • Aware
    • 这是一种模式 Aware前面是类型
    • 会注入ApplicationContext 同理BeanFactoryAware也是一样
    • 这是一种接口的方式,称为Aware接口回调
      • 每当Bean实现这样一种接口的时候会回调一个对象(ApplicationContext 、BeanFactory)
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @author Chris Beams
 * @see ResourceLoaderAware
 * @see ApplicationEventPublisherAware
 * @see MessageSourceAware
 * @see org.springframework.context.support.ApplicationObjectSupport
 * @see org.springframework.beans.factory.BeanFactoryAware
 */
public interface ApplicationContextAware extends Aware {

	/**
	 * Set the ApplicationContext that this object runs in.
	 * Normally this call will be used to initialize the object.
	 * <p>Invoked after population of normal bean properties but before an init callback such
	 * as {@link org.springframework.beans.factory.InitializingBean#afterPropertiesSet()}
	 * or a custom init-method. Invoked after {@link ResourceLoaderAware#setResourceLoader},
	 * {@link ApplicationEventPublisherAware#setApplicationEventPublisher} and
	 * {@link MessageSourceAware}, if applicable.
	 * @param applicationContext the ApplicationContext object to be used by this object
	 * @throws ApplicationContextException in case of context initialization errors
	 * @throws BeansException if thrown by application context methods
	 * @see org.springframework.beans.factory.BeanInitializationException
	 */
	void setApplicationContext(ApplicationContext applicationContext) throws BeansException;

}

  • BeanPostProcessor
    • 这是一个关于Bean生命周期的后置处理
    • 在这里spring使用了default的java8的实现直接返回了,也就是不对Bean做任何处理和扩展
    • 所以这里我们可以覆盖
public interface BeanPostProcessor {
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

设计模式

  • 观察者模式
    • ApplicationEvent
public abstract class ApplicationEvent extends EventObject {

	/** use serialVersionUID from Spring 1.2 for interoperability. */
	private static final long serialVersionUID = 7099057708183571937L;

	/** System time when the event happened. */
	private final long timestamp;


	/**
	 * Create a new {@code ApplicationEvent}.
	 * @param source the object on which the event initially occurred or with
	 * which the event is associated (never {@code null})
	 */
	public ApplicationEvent(Object source) {
		super(source);
		this.timestamp = System.currentTimeMillis();
	}


	/**
	 * Return the system time in milliseconds when the event occurred.
	 */
	public final long getTimestamp() {
		return this.timestamp;
	}

}

ApplicationEvent 基于java的标准事件EventObject

public class EventObject implements java.io.Serializable {

    private static final long serialVersionUID = 5516075349620653480L;

    /**
     * The object on which the Event initially occurred.
     */
    protected transient Object  source;

    /**
     * Constructs a prototypical Event.
     *
     * @param    source    The object on which the Event initially occurred.
     * @exception  IllegalArgumentException  if source is null.
     */
    public EventObject(Object source) {
        if (source == null)
            throw new IllegalArgumentException("null source");

        this.source = source;
    }

    /**
     * The object on which the Event initially occurred.
     *
     * @return   The object on which the Event initially occurred.
     */
    public Object getSource() {
        return source;
    }

    /**
     * Returns a String representation of this EventObject.
     *
     * @return  A a String representation of this EventObject.
     */
    public String toString() {
        return getClass().getName() + "[source=" + source + "]";
    }
}

  • 有一个简单的实现
  • 通过事件的方式让监听器进行状态的回调
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {

	@Nullable
	private Executor taskExecutor;

	@Nullable
	private ErrorHandler errorHandler;
	
	@Override
	public void multicastEvent(ApplicationEvent event) {
		multicastEvent(event, resolveDefaultEventType(event));
	}

	@Override
	public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
		Executor executor = getTaskExecutor();
		for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
			if (executor != null) {
				executor.execute(() -> invokeListener(listener, event));
			}
			else {
				invokeListener(listener, event);
			}
		}
	}

}

@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

	/**
	 * Handle an application event.
	 * @param event the event to respond to
	 */
	void onApplicationEvent(E event);

}
  • 组合模式
    • CompositeCacheManager
      • 实现了CacheManager而后组合了更多成员List<CacheManager> cacheManagers
      • 此处是多个缓存合并后按照同一个处理方式进行处理
public class CompositeCacheManager implements CacheManager, InitializingBean {

	private final List<CacheManager> cacheManagers = new ArrayList<>();

	private boolean fallbackToNoOpCache = false;
}
  • 模板模式
    • JdbcTemplate
public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
    private static final String RETURN_RESULT_SET_PREFIX = "#result-set-";
    private static final String RETURN_UPDATE_COUNT_PREFIX = "#update-count-";
    private boolean ignoreWarnings = true;
    private int fetchSize = -1;
    private int maxRows = -1;
    private int queryTimeout = -1;
    private boolean skipResultsProcessing = false;
    private boolean skipUndeclaredResults = false;
    private boolean resultsMapCaseInsensitive = false;
    @Nullable
    public <T> T execute(ConnectionCallback<T> action) throws DataAccessException {
        Assert.notNull(action, "Callback object must not be null");
        Connection con = DataSourceUtils.getConnection(this.obtainDataSource());

        Object var10;
        try {
            Connection conToUse = this.createConnectionProxy(con);
            var10 = action.doInConnection(conToUse);
        } catch (SQLException var8) {
            String sql = getSql(action);
            DataSourceUtils.releaseConnection(con, this.getDataSource());
            con = null;
            throw this.translateException("ConnectionCallback", sql, var8);
        } finally {
            DataSourceUtils.releaseConnection(con, this.getDataSource());
        }

        return var10;
    }
    
    @Nullable
    public <T> T execute(StatementCallback<T> action) throws DataAccessException {
        Assert.notNull(action, "Callback object must not be null");
        Connection con = DataSourceUtils.getConnection(this.obtainDataSource());
        Statement stmt = null;

        Object var11;
        try {
            stmt = con.createStatement();
            this.applyStatementSettings(stmt);
            T result = action.doInStatement(stmt);
            this.handleWarnings(stmt);
            var11 = result;
        } catch (SQLException var9) {
            String sql = getSql(action);
            JdbcUtils.closeStatement(stmt);
            stmt = null;
            DataSourceUtils.releaseConnection(con, this.getDataSource());
            con = null;
            throw this.translateException("StatementCallback", sql, var9);
        } finally {
            JdbcUtils.closeStatement(stmt);
            DataSourceUtils.releaseConnection(con, this.getDataSource());
        }

        return var11;
    }
}

对象继承

  • 很多Abstract*抽象类
  • 例如AbstractApplicationContext 、AbstractBeanFactory 有很多继承实现类
public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {}
		
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport 
		implements ConfigurableBeanFactory {}

面向切面

动态代理

  • JdkDynamicAopProxy 代理了AopProxy
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
	private static final long serialVersionUID = 5531744639992436476L;
    private static final Log logger = LogFactory.getLog(JdkDynamicAopProxy.class);
    private final AdvisedSupport advised;
    private boolean equalsDefined;
    private boolean hashCodeDefined;

    public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
        Assert.notNull(config, "AdvisedSupport must not be null");
        if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
            throw new AopConfigException("No advisors and no TargetSource specified");
        } else {
            this.advised = config;
        }
    }

    public Object getProxy() {
        return this.getProxy(ClassUtils.getDefaultClassLoader());
    }

}

public interface AopProxy {
    Object getProxy();

    Object getProxy(@Nullable ClassLoader var1);
}

字节码提升

  • AopProxy的多种实现之CglibAopProxy
    • 这是Spring为了保证版本稳定性将Cglib内联进自己核心框架中了(asm自动资源管理也是类似的方式)
    • asm是Cglib的基础,是对java字节码的类似于汇编一样的操作
lass CglibAopProxy implements AopProxy, Serializable {
    private static final int AOP_PROXY = 0;
    private static final int INVOKE_TARGET = 1;
    private static final int NO_OVERRIDE = 2;
    private static final int DISPATCH_TARGET = 3;
    private static final int DISPATCH_ADVISED = 4;
    private static final int INVOKE_EQUALS = 5;
    private static final int INVOKE_HASHCODE = 6;
    protected static final Log logger = LogFactory.getLog(CglibAopProxy.class);
    private static final Map<Class<?>, Boolean> validatedClasses = new WeakHashMap();
    protected final AdvisedSupport advised;
    @Nullable
    protected Object[] constructorArgs;
    @Nullable
    protected Class<?>[] constructorArgTypes;
    private final transient CglibAopProxy.AdvisedDispatcher advisedDispatcher;
    private transient Map<Method, Integer> fixedInterceptorMap = Collections.emptyMap();
    private transient int fixedInterceptorOffset;

    public CglibAopProxy(AdvisedSupport config) throws AopConfigException {
        Assert.notNull(config, "AdvisedSupport must not be null");
        if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
            throw new AopConfigException("No advisors and no TargetSource specified");
        } else {
            this.advised = config;
            this.advisedDispatcher = new CglibAopProxy.AdvisedDispatcher(this.advised);
        }
    }
}

面向元编程

注解

  • Component (组件)注解
  • 被ComponentScan注解或者相应注解扫描到会变成一个Bean

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
    String value() default "";
}

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
    @AliasFor("basePackages")
    String[] value() default {};

    @AliasFor("value")
    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};

    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

    Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;

    ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;

    String resourcePattern() default "**/*.class";

    boolean useDefaultFilters() default true;

    ComponentScan.Filter[] includeFilters() default {};

    ComponentScan.Filter[] excludeFilters() default {};

    boolean lazyInit() default false;

    @Retention(RetentionPolicy.RUNTIME)
    @Target({})
    public @interface Filter {
        FilterType type() default FilterType.ANNOTATION;

        @AliasFor("classes")
        Class<?>[] value() default {};

        @AliasFor("value")
        Class<?>[] classes() default {};

        String[] pattern() default {};
    }
}

  • Component 的派生类Repository (Service和Controller等也是这种方式)
    • 标注了@Component就意味着Repository 等同于Component
    • 进行标注是因为注解没有继承关系所以只能进行源标注
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {

	/**
	 * The value may indicate a suggestion for a logical component name,
	 * to be turned into a Spring bean in case of an autodetected component.
	 * @return the suggested component name, if any (or empty String otherwise)
	 */
	@AliasFor(annotation = Component.class)
	String value() default "";

}

配置

  • Profiles可以认为是不同的用户配置对不同的系统来进行区分例如(dev sit uat pod)
public interface Environment extends PropertyResolver {
    String[] getActiveProfiles();

    String[] getDefaultProfiles();

    /** @deprecated */
    @Deprecated
    boolean acceptsProfiles(String... var1);

    boolean acceptsProfiles(Profiles var1);
}

  • 属性(数据源来自于多个PropertySource )
public interface PropertyResolver {
    boolean containsProperty(String var1);

    @Nullable
    String getProperty(String var1);

    String getProperty(String var1, String var2);

    @Nullable
    <T> T getProperty(String var1, Class<T> var2);

    <T> T getProperty(String var1, Class<T> var2, T var3);

    String getRequiredProperty(String var1) throws IllegalStateException;

    <T> T getRequiredProperty(String var1, Class<T> var2) throws IllegalStateException;

    String resolvePlaceholders(String var1);

    String resolveRequiredPlaceholders(String var1) throws IllegalArgumentException;
}

  • PropertySource
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(PropertySources.class)
public @interface PropertySource {

	/**
	 * Indicate the name of this property source. If omitted, a name will
	 * be generated based on the description of the underlying resource.
	 * @see org.springframework.core.env.PropertySource#getName()
	 * @see org.springframework.core.io.Resource#getDescription()
	 */
	String name() default "";

	/**
	 * Indicate the resource location(s) of the properties file to be loaded.
	 * <p>Both traditional and XML-based properties file formats are supported
	 * &mdash; for example, {@code "classpath:/com/myco/app.properties"}
	 * or {@code "file:/path/to/file.xml"}.
	 * <p>Resource location wildcards (e.g. *&#42;/*.properties) are not permitted;
	 * each location must evaluate to exactly one {@code .properties} resource.
	 * <p>${...} placeholders will be resolved against any/all property sources already
	 * registered with the {@code Environment}. See {@linkplain PropertySource above}
	 * for examples.
	 * <p>Each location will be added to the enclosing {@code Environment} as its own
	 * property source, and in the order declared.
	 */
	String[] value();

	/**
	 * Indicate if failure to find the a {@link #value() property resource} should be
	 * ignored.
	 * <p>{@code true} is appropriate if the properties file is completely optional.
	 * Default is {@code false}.
	 * @since 4.0
	 */
	boolean ignoreResourceNotFound() default false;

	/**
	 * A specific character encoding for the given resources, e.g. "UTF-8".
	 * @since 4.3
	 */
	String encoding() default "";

	/**
	 * Specify a custom {@link PropertySourceFactory}, if any.
	 * <p>By default, a default factory for standard resource files will be used.
	 * @since 4.3
	 * @see org.springframework.core.io.support.DefaultPropertySourceFactory
	 * @see org.springframework.core.io.support.ResourcePropertySource
	 */
	Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;

}

泛型

  • GenericTypeResolver
public final class GenericTypeResolver {
    private static final Map<Class<?>, Map<TypeVariable, Type>> typeVariableCache = new ConcurrentReferenceHashMap();

    private GenericTypeResolver() {
    }
}
public interface TypeVariable<D extends GenericDeclaration> 
		extends Type, AnnotatedElement {
}
  • ResolvableType
    • 有示例如何获取泛型
public class ResolvableType implements Serializable {
}

在这里插入图片描述

函数驱动

函数接口

  • 有且仅有一个抽象方法,排除掉Object里面的equals,hashCode方法以及一些default实现,此时无论标注或者不标注@FunctionalInterface 都可以认为是函数接口
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}

  • 例如
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

	/**
	 * Handle an application event.
	 * @param event the event to respond to
	 */
	void onApplicationEvent(E event);

}

Reactive

  • Reactive的实现框架Reactor
  • 编程框架 Mono、Flux
    • Mono可以简单认为是个单一对象(0或者1个)
    • Flux是个集合对象
public abstract class Mono<T> implements CorePublisher<T> {
    static final BiPredicate EQUALS_BIPREDICATE = Object::equals;

    public Mono() {
    }
}

public abstract class Flux<T> implements CorePublisher<T> {
    static final BiFunction TUPLE2_BIFUNCTION = Tuples::of;
    static final Supplier LIST_SUPPLIER = ArrayList::new;
    static final Supplier SET_SUPPLIER = HashSet::new;
    static final BooleanSupplier ALWAYS_BOOLEAN_SUPPLIER = () -> {
        return true;
    };
    static final BiPredicate OBJECT_EQUAL = Object::equals;
    static final Function IDENTITY_FUNCTION = Function.identity();

    public Flux() {
    }
}

模块驱动

  • Enable
    • 例如EnableCaching 激活整个缓存部分
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(CachingConfigurationSelector.class)
public @interface EnableCaching {
}
  • EnableTransactionManagement 激活整个事务相关模块
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({TransactionManagementConfigurationSelector.class})
public @interface EnableTransactionManagement {
    boolean proxyTargetClass() default false;

    AdviceMode mode() default AdviceMode.PROXY;

    int order() default 2147483647;
}
  • EnableWebMvc激活WebMVC
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({DelegatingWebMvcConfiguration.class})
public @interface EnableWebMvc {
}

  • EnableWebFlux 激活WebFlux
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({DelegatingWebFluxConfiguration.class})
public @interface EnableWebFlux {
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值