做网站毕设任务书,怎么自己搭建一个博客网站,域名解析查询入口,wordpress 负载简单工厂
实现方式#xff1a; BeanFactory。Spring中的BeanFactory就是简单工厂模式的体现#xff0c;根据传入一个唯一的标识来获得Bean对象#xff0c;但是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定。 实质#xff1a; 由一个工厂… 简单工厂
实现方式 BeanFactory。Spring中的BeanFactory就是简单工厂模式的体现根据传入一个唯一的标识来获得Bean对象但是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定。 实质 由一个工厂类根据传入的参数动态决定应该创建哪一个产品类。 实现原理
bean容器的启动阶段
读取bean的配置,将bean元素分别转换成一个BeanDefinition对象。然后通过BeanDefinitionRegistry将这些bean注册到beanFactory中保存在它的一个ConcurrentHashMap中。将BeanDefinition注册到了beanFactory之后在这里Spring为我们提供了一个扩展的切口允许我们通过实现接口BeanFactoryPostProcessor 在此处来插入我们定义的代码。典型的例子就是PropertyPlaceholderConfigurer我们一般在配置数据库的dataSource时使用到的占位符的值就是它注入进去的。
容器中bean的实例化阶段 实例化阶段主要是通过反射或者CGLIB对bean进行实例化在这个阶段Spring又给我们暴露了很多的扩展点
各种的Aware接口比如 BeanFactoryAware对于实现了这些Aware接口的bean在实例化bean时Spring会帮我们注入BeanFactory接口对应的具体实例BeanPostProcessor接口实现了BeanPostProcessor接口的bean在实例化bean时Spring会帮我们调用接口中的方法InitializingBean接口实现了InitializingBean接口的bean在实例化bean时Spring会帮我们调用接口中的方法DisposableBean接口实现了DisposableBean接口的bean在该bean死亡时Spring会帮我们调用接口中的方法
设计意义 松耦合。可以将原来硬编码的依赖通过Spring这个beanFactory这个工厂来注入依赖也就是说原来只有依赖方和被依赖方现在我们引入了第三方——spring这个beanFactory由它来解决bean之间的依赖问题达到了松耦合的效果
bean的额外处理
通过Spring接口的暴露在实例化bean的阶段我们可以进行一些额外的处理这些额外的处理只需要让bean实现对应的接口即可那么spring就会在bean的生命周期调用我们实现的接口来处理该bean。[非常重要] 工厂方法
实现方式 FactoryBean接口。 实现原理 实现了FactoryBean接口的bean是一类叫做factory的bean。其特点是spring会在使用getBean()调用获得该bean时会自动调用该bean的getObject()方法所以返回的不是factory这个bean而是这个bean.getOjbect()方法的返回值 例子 典型的例子有spring与mybatis的结合。 我们看上面该bean因为实现了FactoryBean接口所以返回的不是SqlSessionFactoryBean 的实例而是它的SqlSessionFactoryBean.getObject() 的返回值 适配器模式
实现方式SpringMVC中的适配器HandlerAdatper。 实现原理HandlerAdatper根据Handler规则执行不同的Handler。 实现过程DispatcherServlet根据HandlerMapping返回的handler向HandlerAdatper发起请求处理Handler。HandlerAdapter根据规则找到对应的Handler并让其执行执行完毕后Handler会向HandlerAdapter返回一个ModelAndView最后由HandlerAdapter向DispatchServelet返回一个ModelAndView。 实现意义HandlerAdatper使得Handler的扩展变得容易只需要增加一个新的Handler和一个对应的HandlerAdapter即可。
因此Spring定义了一个适配接口使得每一种ControllerHandler有一种对应的适配器实现类让适配器代替controller执行相应的方法。这样在扩展Controller时只需要增加一个适配器类就完成了SpringMVC的扩展了
package org.springframework.web.servlet;public interface HandlerAdapter {boolean supports(Object handler);ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}针对不同的Handler定义不同的HandlerAdapter接口实现类
public class SimpleControllerHandlerAdapter implements HandlerAdapter {Overridepublic boolean supports(Object handler) {return (handler instanceof Controller);}Overridepublic ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {return ((Controller) handler).handleRequest(request, response);}
}
这是针对Controller类型的
public class SimpleServletHandlerAdapter implements HandlerAdapter {Overridepublic boolean supports(Object handler) {return (handler instanceof Servlet);}Overridepublic ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {((Servlet) handler).service(request, response);return null;}
}
这是针对Handler是原生Servlet类型的
public class HttpRequestHandlerAdapter implements HandlerAdapter {Overridepublic boolean supports(Object handler) {return (handler instanceof HttpRequestHandler);}Overridepublic ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {((HttpRequestHandler) handler).handleRequest(request, response);return null;}
}
这是针对Handler是HttpRequestHandler类型的 装饰器模式
实现方式Spring中用到的包装器模式在类名上有两种表现一种是类名中含有Wrapper另一种是类名中含有Decorator 实质动态地给一个对象添加一些额外的职责。就增加功能来说Decorator模式相比生成子类更为灵活 代理模式
实现方式AOP底层就是动态代理模式的实现。 动态代理在内存中构建的不需要手动编写代理类静态代理需要手工编写代理类代理类引用被代理对象。 实现原理 切面在应用运行的时刻被织入。一般情况下在织入切面时AOP容器会为目标对象创建动态的创建一个代理对象。SpringAOP就是以这种方式织入切面的。 织入把切面应用到目标对象并创建新的代理对象的过程。 观察者模式
实现方式spring的事件驱动模型使用的是 观察者模式 Spring中Observer观察者模式常用的地方是listener的实现 具体实现事件机制的实现需要三个部分、事件源、事件、事件监听器 ApplicationEvent事件抽象类继承自jdk的EventObject所有的事件都需要继承ApplicationEvent并且通过构造器参数source得到事件源。该类ApplicationEvent的实现类ApplicationContextEvent表示ApplicaitonContext的容器事件.
ApplicationListener事件监听器口继承自jdk的EventListener所有的监听器都要实现这个接口。 这个接口只有一个onApplicationEvent()方法该方法接受一个ApplicationEvent或其子类对象作为参数。在方法体中,可以通过不同对Event类的判断来进行相应的处理。当事件触发时所有的监听器都会收到消息。
ApplicationContext事件源接口ApplicationContext是spring中的全局容器翻译过来是”应用上下 文”ApplicationContext实现了ApplicationEventPublisher接口它负责读取bean的配置文件、管理bean的加载、维护bean之间的依赖关系可以说是负责bean的整个生命周期再通俗一点就是我们平时所说的IOC容器
ApplicationEventMulticaster抽象类ApplicationContext事件源接口的publishEvent方法需要调用其方法getApplicationEventMulticaster它属于事件广播器作用是把Applicationcontext发布的Event广播给所有的监听器
public interface ApplicationEventMulticaster {void addApplicationListener(ApplicationListener? listener);void addApplicationListenerBean(String listenerBeanName);void removeApplicationListener(ApplicationListener? listener);void removeApplicationListenerBean(String listenerBeanName);void removeAllListeners();void multicastEvent(ApplicationEvent event);void multicastEvent(ApplicationEvent event, Nullable ResolvableType eventType);
}
事件多播器1.管理各个监听器、2. 向监听器发布事件
public abstract class AbstractApplicationContext extends DefaultResourceLoaderimplements ConfigurableApplicationContext {protected void registerListeners() {// Register statically specified listeners first.for (ApplicationListener? listener : getApplicationListeners()) {getApplicationEventMulticaster().addApplicationListener(listener);}// Do not initialize FactoryBeans here: We need to leave all regular beans// uninitialized to let post-processors apply to them!String[] listenerBeanNames getBeanNamesForType(ApplicationListener.class, true, false);for (String listenerBeanName : listenerBeanNames) {getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);}}
}
注册监听器registerListeners()作为AbstractApplicationContext#refresh()方法中的一个核心步骤
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {Overridepublic void multicastEvent(final ApplicationEvent event, Nullable ResolvableType eventType) {ResolvableType type (eventType ! null ? eventType : resolveDefaultEventType(event));for (final ApplicationListener? listener : getApplicationListeners(event, type)) {Executor executor getTaskExecutor();if (executor ! null) {executor.execute(() - invokeListener(listener, event));}else {invokeListener(listener, event);}}}
} 策略模式
实现方式Spring框架的资源访问Resource接口。该接口提供了更强的资源访问能力Spring 框架本身大量使用了 Resource 接口来访问底层资源 Resource 接口介绍source 接口是具体资源访问策略的抽象也是所有资源访问类所实现的接口。 Resource 接口主要提供了如下几个方法: getInputStream()定位并打开资源返回资源对应的输入流。每次调用都返回新的输入流。调用者必须负责关闭输入流。 exists()返回 Resource 所指向的资源是否存在。 isOpen()返回资源文件是否打开如果资源文件不能多次读取每次读取结束应该显式关闭以防止资源泄漏。 getDescription()返回资源的描述信息通常用于资源处理出错时输出该信息通常是全限定文件名或实际 URL getFile返回资源对应的 File 对象 getURL返回资源对应的 URL 对象 最后两个方法通常无须使用仅在通过简单方式访问无法实现时 Resource 提供传统的资源访问的功能。 Resource 接口本身没有提供访问任何底层资源的实现逻辑针对不同的底层资源Spring 将会提供不同的 Resource 实现类不同的实现类负责不同的资源访问逻辑。 Spring 为 Resource 接口提供了如下实现类 UrlResource访问网络资源的实现类。 ClassPathResource访问类加载路径里资源的实现类。 FileSystemResource访问文件系统里资源的实现类。 ServletContextResource访问相对于 ServletContext 路径里的资源的实现类. InputStreamResource访问输入流资源的实现类。 ByteArrayResource访问字节数组资源的实现类。 这些 Resource 实现类针对不同的的底层资源提供了相应的资源访问逻辑并提供便捷的包装以利于客户端程序的资源访问 模版方法模式
经典模板方法定义父类定义了骨架调用哪些方法及顺序某些特定方法由子类实现。
最大的好处代码复用减少重复代码。除了子类要实现的特定方法其他方法及方法调用顺序都在父类中预先写好了。 所以父类模板方法中有两类方法共同的方法所有子类都会用到的代码、不同的方法子类要覆盖的方法分为两种
抽象方法父类中的是抽象方法子类必须覆盖钩子方法父类中是一个空方法子类继承了默认也是空的
注为什么叫钩子子类可以通过这个钩子方法控制父类因为 这个钩子实际是父类的方法空方法
Spring模板方法模式实质 是模板方法模式和回调模式的结合是Template Method不需要继承的另一种实现方式。Spring几乎所有的外接扩展都采用这种模式
具体实现 Spring对于JDBC的抽象和对Hibernate的集成都采用了一种理念或者处理方式那就是模板方法模式与相应的Callback接口相结合。采用模板方法模式是为了以一种统一而集中的方式来处理资源的获取和释放以JdbcTempalte为例:
public abstract class JdbcTemplate {public final Object execute(String sql) {Connection con null;Statement stmt null;try {con getConnection();stmt con.createStatement();Object retValue executeWithStatement(stmt, sql);return retValue;} catch (SQLException e) {// .....} finally {closeStatement(stmt);releaseConnection(con);}}protected abstract Object executeWithStatement(Statement stmt, String sql);
}
以上为传统的模板方法的实现父类定义为抽象类子类必须有自己的实现
引入回调原因 JdbcTemplate是抽象类不能够独立使用我们每次进行数据访问的时候都要给出一个相应的子类实现这样肯定不方便所以引入回调后让JdbcTemplate成为普通类而不需要再成为抽象类就可以直接使用JdbcTemplate类了
// 回调接口
public interface StatementCallbackT{public T doInStatement(Statement stmt) throws SQLException;
}
回调接口使用泛型针对增删改查不同类型的sqldoInStatement()方法可以返回不同类型的对象
为什么JdbcTemplate没有使用继承 因为这个类的方法太多但是我们还是想用到JdbcTemplate已有的稳定的、公用的数据库连接那么我们怎么办呢 我们可以把变化的东西抽出来作为一个参数传入JdbcTemplate的方法中。但是变化的东西是一段代码而且这段代码会用到JdbcTemplate中的变量。怎么办那我们就用回调对象吧。在这个回调对象中定义一个操纵JdbcTemplate中变量的方法我们去实现这个方法就把变化的东西集中到这里了。然后我们再传入这个回调对象到JdbcTemplate从而完成了调用。 核心方法 - JdbcTemplate#execute
实际上无论是query 或者 update其底层调用的都是JdbcTemplate#execute(org.springframework.jdbc.core.StatementCallbackT) 方法。
execute 作为数据库操作的核心入口其实实现逻辑和我们一起最基础的写法类似。将大多数数据库操作对相同的统一封装而将个性化的操作使用 StatementCallback 进行回调并进行数据库资源释放的一些收尾操作。 execute 方法的作用是获取数据库连接准备好Statement 随后调用预先传入的回调方法。
下面我们直接来看 JdbcTemplate#execute(org.springframework.jdbc.core.StatementCallbackT) 方法 public T T execute(StatementCallbackT action) throws DataAccessException {Assert.notNull(action, Callback object must not be null);// 从数据源中获取数据连接Connection con DataSourceUtils.getConnection(obtainDataSource());Statement stmt null;try {// 创建 Statement 。stmt con.createStatement();// 应用一些设置applyStatementSettings(stmt);// 回调执行个性化业务T result action.doInStatement(stmt);// 警告处理handleWarnings(stmt);return result;}catch (SQLException ex) {// Release Connection early, to avoid potential connection pool deadlock// in the case when the exception translator hasnt been initialized yet.// 释放数据库连接避免当异常转换器没有被初始化的时候出现潜在的连接池死锁String sql getSql(action);JdbcUtils.closeStatement(stmt);stmt null;DataSourceUtils.releaseConnection(con, getDataSource());con null;throw translateException(StatementCallback, sql, ex);}finally {JdbcUtils.closeStatement(stmt);DataSourceUtils.releaseConnection(con, getDataSource());}}上面说了 execute 方式是整个JdbcTemplate 的核心其他个性化定制都是在其基础上通过StatementCallback 回调完成的。下面我们简单看一看。
1. Update 中的回调函数 我们挑一个最简单的Update 方法 JdbcTemplate#update(java.lang.String) public int update(final String sql) throws DataAccessException {Assert.notNull(sql, SQL must not be null);if (logger.isDebugEnabled()) {logger.debug(Executing SQL update [ sql ]);}/*** Callback to execute the update statement.*/// 该种形式的回调方法。不同形式的回调实现类并不相同。class UpdateStatementCallback implements StatementCallbackInteger, SqlProvider {// 注意这里泛型返回值为Integer Overridepublic Integer doInStatement(Statement stmt) throws SQLException {// 执行sql 语句// 注意看个性化代码在这里 int rows stmt.executeUpdate(sql);if (logger.isTraceEnabled()) {logger.trace(SQL update affected rows rows);}return rows;}Overridepublic String getSql() {return sql;}}// 通过 execute 将 Statement 回调给 UpdateStatementCallback。return updateCount(execute(new UpdateStatementCallback()));}2. query 功能的实现 可以看到思路基本相同这里不再赘述。 public T T query(final String sql, final ResultSetExtractorT rse) throws DataAccessException {Assert.notNull(sql, SQL must not be null);Assert.notNull(rse, ResultSetExtractor must not be null);if (logger.isDebugEnabled()) {logger.debug(Executing SQL query [ sql ]);}/*** Callback to execute the query.*/class QueryStatementCallback implements StatementCallbackT, SqlProvider {OverrideNullablepublic T doInStatement(Statement stmt) throws SQLException {ResultSet rs null;try {// 注意看个性化代码在这里 rs stmt.executeQuery(sql);return rse.extractData(rs);}finally {JdbcUtils.closeResultSet(rs);}}Overridepublic String getSql() {return sql;}}return execute(new QueryStatementCallback());}参考链接Spring源码分析九JdbcTemplate 的源码分析_猫吻鱼的博客-CSDN博客_jdbctemplate源码 责任链模式
CglibAopProxy类第688行
new CglibMethodInvocation(proxy, target, method, args, targetClass,
chain, methodProxy).proceed();
参数 chain拦截器链保含了目标方法的所有切面方法 从chain里面的数组元素的顺序来看拦截器的顺序每一个 XxxxxxInterceptor有一个invoke()方法Interceptor是一个空接口 MethodInterceptor extends Interceptor 以下是Interceptor的继承结构
public interface Advice {}public interface Interceptor extends Advice {}public interface MethodInterceptor extends Interceptor {Object invoke(MethodInvocation invocation) throws Throwable;
}
Object invoke(MethodInvocation invocation) throws Throwable方法参数 MethodInvocation 类中有proceed()方法以下是MethodInvocation的继承结构
public interface Joinpoint {// 连接点的proceed()方法内部就是真正的目标方法Object proceed() throws Throwable;Object getThis();AccessibleObject getStaticPart();
}public interface Invocation extends Joinpoint {Object[] getArguments();
}public interface MethodInvocation extends Invocation {Method getMethod();
}
MethodInvocation extends Invocation extends JoinPoint。proceed()方法是JoinPoint接口声明的 然后ReflectiveMethodInvocation implements ProxyMethodInvocation ,ProxyMethodInvocation extends MethodInvocation、 Spring的拦截器XxxxxInterceptor都实现了自己的 Object invoke(MethodInvocation invocation)方法 ReflectiveMethodInvocation类中的proceed()方法会遍历拦截器链调用每个拦截器的invoke方法并把传入ReflectiveMethodInvocation自身作为参数传给每个拦截器的invoke方法
每个拦截器的invoke方法做两件事这两件事的执行顺序因拦截器的功能而异
1.执行自己的业务逻辑
2.执行ReflectiveMethodInvocation的proceed()这样就实现了链式调用
这就是责任链模式
统一的业务接口Handler接口 中的方法invoke(),即业务方法责任链相当于一个负责人集合每一个负责人都实现了自己的invoke()方法来处理传进来的数据或对象或对象的指定方法
如何通知下一个负责人处理业务 方法1设计一个责任链执行器包含责任链集合。责任链执行器中有一个proceed()方法内遍历执行负责人的invoke()方法invoke方法以执行器作为参数invoke(执行器)invoke(执行器)处理完业务后执行器又调用proceed()方法将索引移到下一个负责人位置。这样执行器和负责人的方法相互调用而执行器通过移动索引通知下一个负责人处理业务。 方法2基于链表的责任链每一个负责人是一个责任节点Node包含指向下一个负责人的next引用负责人的处理业务的方法 invoke()这时不带参数invoke()方法里面递归调用invoke()方法并设置出口条件。如何通知下一个负责人处理业务invoke()方法1.处理业务2.next.invoke()3.出口条件可以是next!null