随手记录5:通过BeanPostProcessor 实现项目中接口功能增强的操作;
简介
项目中某些已经实现的功能,可能会要求在方法添加额外的操作内容,比如咋方法前面打印日志内容,或者记录接口操作的耗时时间等,已经完善的代码不想大范围的改动,本文通过自定义BeanPostProcessor 实现类来完成当前功能 (/自定义注解/拦截器/代理类 /切面 等都能实现我们的需求)
代码内容
1.自定义SportServiceBeanPostProcessor
public class SportServiceBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// 项目初始化的时间只是将 SportService 接口实现类对象进行下面的代码增强使用;
if(!(bean instanceof SportService)){
return bean;
}
final Object finalBean = bean;
Map<String,Object> map = new ConcurrentHashMap<>(10);
if(null != map.get(beanName)){
return map.get(beanName);
}
Class<?>[] interfaces = bean.getClass().getInterfaces();
//没有实现接口的直接返回
if(null == interfaces || interfaces.length < 1){
return bean;
}
//调用目标对象的方法时执行下面的diamante
Object proxyObj = Proxy.newProxyInstance(this.getClass().getClassLoader(), interfaces, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
//不需要增强的方法直接执行
if(method.getName().equals("equals") || method.getName().equals("toString")){
result = method.invoke(finalBean, args);
}else{
//需要增强的方法将增强的方法写到下面代码中去
System.out.println("method:" + method.getName());
result = method.invoke(finalBean, args);
System.out.println("当前时间:" + (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(new Date()));
}
return result;
}
});
map.put(beanName, proxyObj);
return proxyObj;
}
}
自定义的SportServiceBeanPostProcessor 实现BeanPostProcessor 在postProcessAfterInitialization 方法中通过代理类来完成对应接口的功能
2.Config配置我们自定义的SportServiceBeanPostProcessor
@Configuration
public class Config {
/**
* 注入对应的BeanPostProcessor对象内容;
* 当服务启动之后会调用 SportServiceBeanPostProcessor 的postProcessAfterInitialization 方法
* 根据我们设置的条件拦截那些需要做对应的方法增强使用
* @author khy
* @createTime 2020年11月10日下午3:03:36
* @return
*/
@Bean
public SportServiceBeanPostProcessor init(){
SportServiceBeanPostProcessor postProcessor = new SportServiceBeanPostProcessor();
return postProcessor;
}
}
3.需要增强的SportService接口和实现类
4.KhyController 中的代码
@RestController
@RequestMapping("/khy")
public class KhyController {
//这里注入的对象不变,其实已经是我们设置的代理对象
@Autowired
private SportService sportService;
@RequestMapping("/test")
public String test(){
sportService.run("学习的道路");
sportService.sleep("很爽");
return "方法执行完毕";
}
}
总结
项目启动之后会加载自定义的SportServiceBeanPostProcessor ,但是在
postProcessAfterInitialization 方法中,通过代理对象完成我们目标对象的功能在代理对象中设置需要添加的方法内容.比我们之前的文章通过FactoryBean类增强接口 的方式的优点在于
依然可以通过我们的@Autowired注解注入,这样之前已经完成的代码不需要大范围的改动即可完成功能实现.