通常应用程序开发人员不需要实现 ApplicationContext 的子类。相反,Spring IoC 容器提供了相当功能丰富的扩展点供开发者进行一些自定义的操作。比如BeanPostProcessor
可以在 Spring 容器完成实例化、配置和初始化 Bean 后实现一些自定义逻辑可以插入一个或多个自定义 BeanPostProcessor 实现来覆盖容器的默认值,自定义实例化逻辑、依赖项解析逻辑等。
下面介绍下怎么使用
首先看下源码
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;
}
}
可以看到该接口有两个方法postProcessBeforeInitialization和postProcessAfterInitialization,这两个方法入参数相同
Object bean:容器正在创建的那个bean的引用
String beanName:容器正在创建的那个bean的名称
下图表现Spring
容器创建bean
的具体过程,其中BeanPostProcessor前置处理和后置处理是BeanPostProcessor在整个bean的生命周期中调用的位置
BeanPostProcessor被经常用在使用代理模式的框架设计中,比如spring中的事务,以及spring aop代理等。那么有时开发者需要自己去定义代理的方式实现某些功能,比如下面要介绍的用自定义注解做登录拦截。
自定义注解,实现访问有该注解的控制器下的所有接口,必须先登录。
1. 简单定义一个注解
import java.lang.annotation.*;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface LoginRequired {
}
2. 声明BeanPostProcessor实例
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.lang.reflect.Method;
/**
* @author: Jiajiajia
*/
@Component
public class LoginBeanPostProcessor implements BeanPostProcessor , Ordered {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
Class<?> beanClass = bean.getClass();
boolean hasLoginRequired = hasLoginRequired(beanClass);
if(hasLoginRequired){
// 对目标类进行代理
Enhancer eh = new Enhancer();
eh.setSuperclass(bean.getClass());
eh.setCallback(new Interceptor());
return eh.create();
}
return bean;
}
public boolean hasLoginRequired(Class<?> clazz){
LoginRequired annotation = clazz.getAnnotation(LoginRequired.class);
if(annotation != null){
return true;
}else{
if(clazz.getSuperclass() == Object.class || clazz.getSuperclass() == null){
return false;
}else{
return hasLoginRequired(clazz.getSuperclass());
}
}
}
@Override
public int getOrder() {
return 0;
}
}
/**
* *方法拦截器
*/
class Interceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// 目标方法执行之前 判断是否登录
if(没有登录){
抛异常
}
Object o = proxy.invokeSuper(obj, args);
return o;
}
}