spring中BeanPostProcessor接口的作用与应用

weblog Md 2843 0 0

  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;
    }
}

  上面的代码只是一个简单的例子,还有很多的使用方法还需要看具体的业务,以及开发者们的设计能力。


猜你喜欢
ASM,java基础 1101 、InvocationHandler  InvocationHandler可以实现对代理,类似mybatis,代码开发者只需要写一个和一个xml,mybatis会根据xml描述信息,帮你生成对方法实现,参数解析
数据结构与算法 1704 表达式:ab+ab-*高级语言自然语言缀表达式,但是计算机对缀表达式处理是非常困难,而对后缀或前缀表达式则显得非常简单后缀表达式特点: 1.在后缀表达式,变量(操数)出现顺序
工具 2905 /dependency2.java代码调SoapClientclient=SoapClient.create("http://cwzf.zzcsjr.edu.cn/xysf/OrderView.asmx")//设
spring/springmvc 1630 "spring在ioc容器获取aop受理对象",这句话是什么意思呢?有时候我们会在spring项目对一下类进行代理,比如我们会springaop和自定义注解对一些访问添加日志,再比如对
框架 5492 springmvc项目,如一个项目页面调另一个项目会产生跨域问题403。对于一个而言很好解决跨域问题,springmvc只需要在上加一个注解。@CrossOrigin
official 871 程序(程序员/编程人员)使,可以理解为一种可供程序调特殊函数,程序可以发出系统调请求来获得操系统服务。程序通过系统调请求操系统服务。系统各种共享资源都由操
框架 1963 springboot获取项目所有对外提供信息@ComponentpublicclassTestimplementsApplicationRunner
框架 1633 能手动去写这些逻辑。最终把它封装成一个可以方便直转换成对象得工具类。首先明确我们得目是什么现有一个excel表,如下图:现需要把excel表每一行都封装在一个java对象,当然如果poia
目录
没有一个冬天不可逾越,没有一个春天不会来临。最慢的步伐不是跬步,而是徘徊,最快的脚步不是冲刺,而是坚持。