spring中BeanPostProcessor接口的作用与应用
BeanPostProcessor是Spring IOC容器给我们提供的一个扩展接口。,他的作用主要是如果我们需要在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:该方法在bean初始化方法调用前被调用,也就是有@PostConstruct注解的方法。
- postProcessAfterInitialization:该方法在bean初始化方法调用后被调用,注意,如果bean有代理的话,那么该bean是被代理后的对象。
一、如何利用BeanPostProcessor
BeanPostProcessor被经常用在使用代理模式的框架设计中,比如spring中的事务,以及spring aop代理等。那么有时开发者需要自己去定义代理的方式实现某些功能,比如下面要介绍的用自定义注解做登录拦截。
自定义注解,实现访问有该注解的控制器下的所有接口,必须先登录。
1、简单定义一个注解
import java.lang.annotation.*;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface LoginRequired {
}
1、声明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;
}
}
上面的代码只是一个简单的例子,还有很多的使用方法还需要看具体的业务,以及开发者们的设计能力。
fixed
没有一个冬天不可逾越,没有一个春天不会来临。最慢的步伐不是跬步,而是徘徊,最快的脚步不是冲刺,而是坚持。