好记忆不如烂笔头,能记下点东西,就记下点,有时间拿出来看看,也会发觉不一样的感受.
目录
Spring 框架具有强大的扩展性,通过各种扩展点可以实现丰富的自定义功能,提升开发效率和灵活性。
当我们提到 Spring 时,映入脑海的是 IOC(控制反转)和 AOP(面向切面编程)。
Spring 具有很强的扩展性。许多第三方应用程序,如 rocketmq、mybatis、redis 等,都可以轻松集成到 Spring 系统中。让我们来看看 Spring 的那些常用的扩展点。
1. 全局异常处理
描述
全局异常处理用于统一处理项目中的异常,避免在每个接口中重复编写异常处理代码,提升代码的可维护性和用户体验。
使用场景
当项目中有大量接口时,统一处理异常,避免重复代码。
示例代码
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public String handleException(Exception e) {
if (e instanceof ArithmeticException) {
return "params error";
}
if (e instanceof Exception) {
return "Internal server exception";
}
return null;
}
}
2. 自定义拦截器
描述
自定义拦截器用于在请求处理过程中插入自定义逻辑,例如权限验证、日志记录等。
使用场景
需要在请求处理前后执行某些逻辑,如权限校验、日志记录。
示例代码
public class AuthInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String requestUrl = request.getRequestURI();
if (checkAuth(requestUrl)) {
return true;
}
return false;
}
private boolean checkAuth(String requestUrl) {
System.out.println("===Authority Verification===");
return true;
}
}
@Configuration
public class WebAuthConfig extends WebMvcConfigurerAdapter {
@Bean
public AuthInterceptor getAuthInterceptor() {
return new AuthInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthInterceptor());
}
}
3. 获取 Spring 容器对象
描述
通过实现特定接口,可以在 Spring 容器中获取 BeanFactory 或 ApplicationContext,从而操作 Spring 容器。
使用场景
需要动态获取 Spring 容器中的 Bean 或操作容器。
示例代码
使用 BeanFactoryAware
@Service
public class StudentService implements BeanFactoryAware {
private BeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
public void add() {
Student student = (Student) beanFactory.getBean("student");
}
}
使用 ApplicationContextAware
@Service
public class StudentService2 implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public void add() {
Student student = (Student) applicationContext.getBean("student");
}
}
4. 导入配置
描述
通过 @Import
注解可以导入其他配置类或普通类到 Spring 容器中。
使用场景
需要将其他类或配置类导入到 Spring 容器中。
示例代码
导入普通类
public class A {
}
@Import(A.class)
@Configuration
public class TestConfiguration {
}
导入带有 @Configuration 注解的配置类
public class A {
}
public class B {
}
@Import(B.class)
@Configuration
public class AConfiguration {
@Bean
public A a() {
return new A();
}
}
@Import(AConfiguration.class)
@Configuration
public class TestConfiguration {
}
使用 ImportSelector
public class AImportSelector implements ImportSelector {
private static final String CLASS_NAME = "com.demo.cache.service.A";
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{CLASS_NAME};
}
}
@Import(AImportSelector.class)
@Configuration
public class TestConfiguration {
}
使用 ImportBeanDefinitionRegistrar
public class AImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(A.class);
registry.registerBeanDefinition("a", rootBeanDefinition);
}
}
@Import(AImportBeanDefinitionRegistrar.class)
@Configuration
public class TestConfiguration {
}
5. 项目启动时的附加功能
描述
通过实现 ApplicationRunner
或 CommandLineRunner
接口,可以在项目启动时执行自定义逻辑。
使用场景
需要在项目启动时加载系统参数、初始化资源等。
示例代码
@Component
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("项目启动时执行附加功能,加载系统参数...");
Properties properties = new Properties();
try (InputStream inputStream = new FileInputStream("application.properties")) {
properties.load(inputStream);
String systemParam = properties.getProperty("system.param");
System.out.println("加载的系统参数值为:" + systemParam);
} catch (IOException e) {
e.printStackTrace();
}
}
}
6. 修改 BeanDefinition
描述
通过实现 BeanFactoryPostProcessor
接口,可以在 Bean 实例化之前修改其定义。
使用场景
需要在 Bean 实例化之前修改其属性或行为。
示例代码
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);
beanDefinitionBuilder.addPropertyValue("id", 123);
beanDefinitionBuilder.addPropertyValue("name", "Dylan Smith");
defaultListableBeanFactory.registerBeanDefinition("user", beanDefinitionBuilder.getBeanDefinition());
}
}
7. 初始化方法
描述
通过 @PostConstruct
注解或实现 InitializingBean
接口,可以在 Bean 初始化时执行自定义逻辑。
使用场景
需要在 Bean 初始化时执行某些操作。
示例代码
使用 @PostConstruct
@Service
public class AService {
@PostConstruct
public void init() {
System.out.println("===Initializing===");
}
}
实现 InitializingBean 接口
@Service
public class BService implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("===Initializing===");
}
}
8. 在初始化 Bean 前后添加逻辑
描述
通过实现 BeanPostProcessor
接口,可以在 Bean 初始化前后插入自定义逻辑。
使用场景
需要在 Bean 初始化前后执行某些操作。
示例代码
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof User) {
((User) bean).setUserName("Dylan Smith");
}
return bean;
}
}
9. 在关闭容器之前添加操作
描述
通过实现 DisposableBean
接口或使用 @PreDestroy
注解,可以在 Spring 容器关闭时执行清理操作。
使用场景
需要在 Spring 容器关闭时释放资源或执行清理操作。
示例代码
@Service
public class DService implements DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean destroy");
}
}
10. 自定义作用域
描述
通过实现 Scope
接口,可以自定义 Bean 的作用域,满足特定场景的需求。
使用场景
默认作用域(如 singleton、prototype)无法满足需求时。
示例代码
实现 Scope 接口
public class ThreadLocalScope implements Scope {
private static final ThreadLocal THREAD_LOCAL_SCOPE = new ThreadLocal();
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
Object value = THREAD_LOCAL_SCOPE.get();
if (value != null) {
return value;
}
Object object = objectFactory.getObject();
THREAD_LOCAL_SCOPE.set(object);
return object;
}
@Override
public Object remove(String name) {
THREAD_LOCAL_SCOPE.remove();
return null;
}
@Override
public void registerDestructionCallback(String name, Runnable callback) {
}
@Override
public Object resolveContextualObject(String key) {
return null;
}
@Override
public String getConversationId() {
return null;
}
}
注入自定义 Scope
@Component
public class ThreadLocalBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcess
}
相知不迷路,来者皆是兄弟!
搜索微信公众号 :“codingba” or “码出精彩” 交朋友,有更多资源