Java面试题:Spring框架除了IOC和AOP,还有哪些好玩的计划模式? ...

打印 上一主题 下一主题

主题 873|帖子 873|积分 2629

Spring是一个基于Java的企业级应用程序开发框架,它利用了多种计划模式来实现其各种特性和功能。本文将介绍一些在Spring中利用的常见计划模式以及相应的代码示例和阐明。

单例模式
单例模式是Spring中最常用的计划模式之一。在ApplicationContext中,Bean默认为单例模式。当我们创建一个Bean时,默认情况下它就是单例的。这意味着当Bean被请求时,Spring会返回相同的实例。下面是一个示例代码:
  1. public class MyBean {
  2.     // ...
  3. }
  4. @Configuration
  5. public class AppConfig {
  6.     @Bean
  7.     public MyBean myBean() {
  8.         return new MyBean();
  9.     }
  10. }
复制代码
在上面的代码中,myBean()方法返回了MyBean类的实例,这个实例将作为单例对象存在于ApplicationContext中。
 
在Spring AOP中,切面默认为单例模式。这意味着切面对象只会创建一次,并与所有目的对象共享。下面的代码演示了怎样在Spring AOP中配置一个单例切面:
  1. @Aspect
  2. @Component
  3. public class LoggingAspect {
  4.     @Before("execution(* com.example.service.*.*(..))")
  5.     public void logBefore(JoinPoint joinPoint) {
  6.         // ...
  7.     }
  8. }
复制代码
这里,LoggingAspect类用@Aspect注解进行了标注,它包罗了@Before通知,该通知将在com.example.service包中的所有方法执行前执行。由于LoggingAspect是一个@Component,以是它将被Spring自动扫描并创建一个单例实例。
在Spring MVC中,控制器(Controller)也通常是单例的。下面是一个简单的控制器类示例:
  1. @Controller
  2. public class UserController {
  3.     @Autowired
  4.     private UserService userService;
  5.     @GetMapping("/users/{id}")
  6.     public ResponseEntity<User> getUserById(@PathVariable Long id) {
  7.         User user = userService.getUserById(id);
  8.         return ResponseEntity.ok(user);
  9.     }
  10. }
复制代码
 
工厂模式
在Spring框架中工厂模式是一种常用的模式之一。下面我将介绍Spring中利用工厂模式的几个具体示例:
BeanFactory
Spring 的焦点容器是BeanFactory和其子接口ApplicationContext。其中,BeanFactory利用了工厂模式来创建和管理bean实例。它包罗了创建、配置和管理 bean 的所有功能,如下所示:
  1. public interface BeanFactory {
  2.     Object getBean(String name) throws BeansException;
  3.     <T> T getBean(String name, Class<T> requiredType) throws BeansException;
  4.     boolean containsBean(String name);
  5. }
复制代码
上述代码中,BeanFactory接口定义了一个getBean()方法,通过传入bean的名称或类型,返回相应的bean实例。这里的getBean()方法就是工厂方法。
 
FactoryBean
FactoryBean 是 Spring 中另一个利用工厂模式的类。它用于创建复杂的 bean,这些 bean 可以有本身的生命周期、作用域和依赖项等。
  1. public interface FactoryBean<T> {
  2.     T getObject() throws Exception;
  3.     Class<?> getObjectType();
  4.     boolean isSingleton();
  5. }
复制代码
述代码中,FactoryBean 定义了一个getObject()方法,用于创建并返回一个特定类型的bean。该方法会在应用程序需要访问bean时被调用。
 
MessageSource
Spring 的国际化支持是基于MessageSource接口实现的。MessageSource为应用程序提供了访问消息资源的方法,如下所示:
  1. public interface MessageSource {
  2.     String getMessage(String code, Object[] args, String defaultMessage, Locale locale);
  3. }
复制代码
上述代码中,getMessage()方法利用工厂模式创建和管理消息资源。它接收消息代码、参数、默认消息和语言环境等参数,并返回相应的消息字符串。
 
代理模式
在Spring AOP中,代理模式被广泛应用。Spring利用JDK动态代理和CGLIB代理来创建切面。下面是一个简单的利用注解方式配置切面的示例:
  1. @Aspect
  2. @Component
  3. public class LoggingAspect {
  4.     @Before("execution(public * com.example.service.*.*(..))")
  5.     public void logBefore(JoinPoint joinPoint) {
  6.         // ...
  7.     }
  8. }
复制代码
在上面的代码中,LoggingAspect类利用了@Aspect和@Component注解进行标注,表明它是一个切面,并会被Spring自动扫描并创建代理对象。在@Before通知中,执行方法调用前进行日志记录。
 
在Spring事务管理中,代理模式也被广泛利用。Spring利用动态代理技术来实现声明式事务管理。下面是一个利用@Transactional注解来声明事务的示例:
  1. @Service
  2. public class UserServiceImpl implements UserService {
  3.     @Autowired
  4.     private UserRepository userRepository;
  5.     @Override
  6.     @Transactional
  7.     public User createUser(User user) {
  8.         return userRepository.save(user);
  9.     }
  10. }
复制代码
在上面的代码中,createUser()方法利用@Transactional注解标记,Spring将在该方法调用之前创建一个代理对象。当然,这只是一个简单的示例,现实上,在复杂的应用程序中,Spring可以再通过多种方式来声明式事务。
 
对于Spring MVC中的控制器类,我们也可以利用代理模式来增强其功能,例如在控制器方法之前和之后添加日志记录。下面是一个基于注解方式实现AOP拦截器的示例:
  1. @Aspect
  2. @Component
  3. public class LoggingInterceptor {
  4.     @Before("execution(* com.example.controller.*.*(..))")
  5.     public void logBefore(JoinPoint joinPoint) {
  6.         // ...
  7.     }
  8.     @AfterReturning(value = "execution(* com.example.controller.*.*(..))", returning = "result")
  9.     public void logAfterReturning(JoinPoint joinPoint, Object result) {
  10.         // ...
  11.     }
  12. }
复制代码
在上面的代码中,LoggingInterceptor类利用了@Aspect和@Component注解进行标注,表明它是一个切面,并且会被Spring自动扫描并创建代理对象。在@Before通知中,执行方法调用前进行日志记录,在@AfterReturning通知中,执行方法调用后进行日志记录。
 
观察者模式
Spring中的变乱机制也是基于观察者模式实现的。在Spring中,所有的Bean都可以作为变乱源发布变乱,其他的Bean则可以通过注册监听器来响应这些变乱。
ApplicationEventPublisher
ApplicationEventPublisher是Spring 框架中利用观察者模式的一个类。它负责发布变乱并通知已注册的监听器。以下是ApplicationEventPublisher的代码示例:
  1. public interface ApplicationEventPublisher {
  2.     void publishEvent(ApplicationEvent event);
  3. }
复制代码
上述代码中,publishEvent()方法用于发布一个变乱,并通知已注册的所有监听器。具体的监听器实现可以通过实现ApplicationListener接口来完成。
 
ApplicationContext 
ApplicationContext是Spring的焦点接口之一。它扩展了BeanFactory接口,并在其底子上添加了更多的功能,例如变乱发布和提供环境信息等。以下是 ApplicationContext利用观察者模式的代码示例:
  1. public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
  2.         MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
  3.     void publishEvent(ApplicationEvent event);
  4.     String[] getBeanNamesForType(ResolvableType type);
  5.     <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException;
  6. }
复制代码
上述代码中,publishEvent()方法也用于发布变乱,并通知已注册的所有监听器。与 ApplicationEventPublisher不同的是,ApplicationContext继承了多个接口,这使得它可以处理各种类型的变乱。
 
BeanPostProcessor 
BeanPostProcessor是Spring框架中一个可插入的回调接口,用于在bean实例化和配置的过程中提供扩展点。以下是BeanPostProcessor利用观察者模式的代码示例:
  1. public interface BeanPostProcessor {
  2.     Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
  3.     Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
  4. }
复制代码
postProcessBeforeInitialization()和postProcessAfterInitialization()方法分别在bean实例化和初始化之前/之后被调用。可以将这些方法视为钩子函数,可以在其中添加自定义逻辑以修改或扩展bean的默认举动。
 
责任链模式 
责任链模式是一种举动型计划模式,它答应你将请求沿着处理链通报,直到其中一个处理程序处理该请求。
HandlerInterceptor 
HandlerInterceptor是Spring MVC中利用责任链模式的一个类。它提供了多个方法,例如 preHandle()、postHandle()和afterCompletion()等,可以在请求处理过程中拦截并修改请求和响应。以下是HandlerInterceptor的代码示例:
  1. public interface HandlerInterceptor {
  2.     boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
  3.     void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
  4.                     @Nullable ModelAndView modelAndView) throws Exception;
  5.     void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
  6.                          @Nullable Exception ex) throws Exception;
  7. }
复制代码
上述代码中,HandlerInterceptor提供了三个方法,分别在请求处理前、处理后、以及完成后调用。通过实现这些方法,在请求处理过程中可以执行自定义逻辑,例如验证用户身份、记录日志等。
 
AbstractRequestLoggingFilter
AbstractRequestLoggingFilter是Spring中利用责任链模式的另一个类。它提供了预先和后续处理请求和响应的方法,可以进行访问日志记录。
以下是 AbstractRequestLoggingFilter的代码示例:
  1. public abstract class AbstractRequestLoggingFilter extends OncePerRequestFilter {
  2.     protected void beforeRequest(HttpServletRequest request, String message) {}
  3.     protected void afterRequest(HttpServletRequest request, String message) {}
  4. }
复制代码
上述代码中,AbstractRequestLoggingFilter的beforeRequest()和afterRequest()方法分别在请求处理前和处理后调用。通过实现这些方法,可以记录访问日志,包括请求的地点、参数等信息。
 
HandlerExceptionResolver
HandlerExceptionResolver是Spring MVC中利用责任链模式的另一个类。它提供了多个方法,例如resolveException()和shouldHandle()等,可以处理异常并决定是否继续执行下一个处理器。以下是HandlerExceptionResolver的代码示例:
  1. public interface HandlerExceptionResolver {
  2.     @Nullable
  3.     ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, @Nullable Object handler,
  4.             Exception ex);
  5.     boolean shouldHandle(HttpServletRequest request, @Nullable Exception ex);
  6. }
复制代码
上述代码中,HandlerExceptionResolver的resolveException()方法用于处理异常并返回ModelAndView对象,该对象可以包罗自定义的错误页面或其他错误信息。而 shouldHandle()方法则用于判断是否应该由当前处理器处理异常,如果返回false,则会继续执行下一个处理器。
 
模板方法模式 
模板方法模式是一种举动型计划模式,它定义了一个算法的骨架,并答应子类实现算法中的某些步调。在Spring框架中,JdbcTemplate和HibernateTemplate就是利用了模板方法模式的例子。
JdbcTemplate 
JdbcTemplate是Spring中利用模板方法模式的一个类。它提供了多个方法,例如 update()、query()等,可以执行SQL语句并返回效果。以下是JdbcTemplate的代码示例:
  1. public class JdbcTemplate {
  2.     public <T> T execute(ConnectionCallback<T> action) throws DataAccessException {
  3.         // ...
  4.     }
  5.     // ...
  6.     public int update(String sql, Object... args) throws DataAccessException {
  7.         // ...
  8.     }
  9.     public <T> List<T> query(String sql, Object[] args, RowMapper<T> rowMapper) throws DataAccessException {
  10.         // ...
  11.     }
  12.     // ...
  13. }
复制代码
上述代码中,JdbcTemplate 提供了execute()、update()和query()等方法,它们都利用了模板方法模式。其中,execute()方法是一个模板方法,它接受一个 ConnectionCallback对象并执行其中的doInConnection()方法,该方法由子类实现。而 update()和 query()方法也是模板方法,它们都调用了execute()方法,并传入不同的参数。
 
HibernateTemplate 
HibernateTemplate是Spring中利用模板方法模式的另一个类。它提供了多个方法,例如 save()、delete()等,可以操纵Hibernate实体并返回效果。以下是HibernateTemplate 的代码示例:
  1. public class HibernateTemplate extends HibernateAccessor {
  2.     public Object execute(HibernateCallback<?> action) throws DataAccessException {
  3.         // ...
  4.     }
  5.     // ...
  6.     public void save(Object entity) throws DataAccessException {
  7.         // ...
  8.     }
  9.     public void delete(Object entity) throws DataAccessException {
  10.         // ...
  11.     }
  12.     // ...
  13. }
复制代码
上述代码中,HibernateTemplate提供了 execute()、save()和 delete()等方法,它们也都利用了模板方法模式。其中,execute()方法是一个模板方法,它接受一个 HibernateCallback对象并执行其中的doInHibernate()方法,该方法由子类实现。而 save()和delete()方法也是模板方法,它们都调用了execute()方法,并传入不同的参数。
 
策略模式
在Spring框架中,策略模式被广泛应用于各种场景,例如事务管理、缓存管理等。以下是 Spring中利用策略模式的几个具体示例:
事务管理 
Spring提供了多种事务管理方式,其中之一就是基于策略模式实现的。该模式下,开发人员需要将不同的事务属性(如传播举动、隔离级别等)封装到TransactionDefinition 接口的实现类中,并将其作为参数通报给PlatformTransactionManager的方法。以下是一个示例代码:
  1. public class TransactionalTest {
  2.     private PlatformTransactionManager transactionManager;
  3.     public void setTransactionManager(PlatformTransactionManager transactionManager) {
  4.         this.transactionManager = transactionManager;
  5.     }
  6.     public void doTransactional() {
  7.         DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
  8.         definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
  9.         definition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
  10.         TransactionStatus status = transactionManager.getTransaction(definition);
  11.         try {
  12.             // 执行事务操作
  13.             transactionManager.commit(status);
  14.         } catch (Exception e) {
  15.             transactionManager.rollback(status);
  16.         }
  17.     }
  18. }
复制代码
上述代码中,TransactionalTest类利用了策略模式来管理事务。它将 DefaultTransactionDefinition对象作为参数通报给PlatformTransactionManager的方法,并在try-catch块中执行事务操纵。
 
缓存管理 
Spring 提供了多种缓存管理方式,其中之一就是基于策略模式实现的。该模式下,开发人员需要将不同的缓存属性(如缓存类型、缓存超时时间等)封装到CacheManager和Cache 接口的实现类中,并将其作为参数通报给CacheResolver和Cache的方法。以下是一个示例代码:
  1. public class CacheTest {
  2.     private CacheResolver cacheResolver;
  3.     public void setCacheResolver(CacheResolver cacheResolver) {
  4.         this.cacheResolver = cacheResolver;
  5.     }
  6.     public void doCached() {
  7.         Cache cache = cacheResolver.resolveCache("myCache");
  8.         Object value = cache.get("myKey");
  9.         if (value == null) {
  10.             // 从数据库或其他存储介质中获取数据
  11.             value = "myValue";
  12.             cache.put("myKey", value);
  13.         }
  14.     }
  15. }
复制代码
上述代码中,CacheTest类利用了策略模式来管理缓存。它将CacheResolver对象作为参数通报给resolveCache()方法,并根据缓存的键值对判断是否需要从缓存中获取数据。
 
往期面试题:
Java面试题:如果你这样做,你会后悔的,两次启动同一个线程~~~
Java面试题:@PostConstruct、init-method和afterPropertiesSet执行顺序?
Java面试题:SimpleDateFormat是线程安全的吗?利用时应该留意什么?
Java面试题:细数ThreadLocal大坑,内存泄露本可避免
Java面试题:请谈谈对ThreadLocal的理解?
Java面试题:为什么HashMap不建议利用对象作为Key?
Java面试题:你知道Spring的IOC吗?那么,它为什么这么重要呢?
Java面试题:线程池内“闹情绪”的线程,怎么办?
Java面试题:Spring Bean线程安全?别担心,只要你不写并发代码就好了!
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

泉缘泉

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表