1、说明
需要对某一类Bean中的所有方法采用同样的处理方式,使用动态代理对类方法增强,所有的Bean都实现都了统一的接口,并在Bean实例化之前对其做代理。
2、自定义根接口
创建一个自定义的根接口,实现该接口或者其子接口的类都将被代理。
public interface MyInterface {}
3、自定义处理过程
为了方便对MyInterface接口的不同子接口做不同的增强过程,将增强的处理过程从InvocationHandler中分离出来。单独创建一个MyInterfaceProcessor接口。getType()用于指定该Processor处理的MyInterface接口(也可以通过注解等形式指定)。
public interface MyInterfaceProcessor<T extends MyInterface> {
//前置过程
default void beforeInvoke(Object target, Method method, Object[] args) throws Throwable {}
//后置过程
default void afterInvoke(Object target, Method method, Object[] args) throws Throwable {}
//该Processor对应的MyInterface接口
Class<T> getType();
}
4、InvocationHandler
创建一个自定义的InvocationHandler对需要增强的Bean进行处理。
public class MyInterfaceInvocationHandler implements InvocationHandler {
private Object target;
//处理过程
public List<MyInterfaceProcessor> processors;
public Object getTarget() {
return target;
}
public void setProcessors(List<MyInterfaceProcessor> processors) {
this.processors = processors;
}
public void setTarget(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//前置过程
for(MyInterfaceProcessor processor: processors)
processor.beforeInvoke(target, method, args);
Object result = method.invoke(target, args);
//后置过程
for(MyInterfaceProcessor processor: processors)
processor.afterInvoke(target, method, args);
return result;
}
}
5、对Bean动态创建代理
通过实现BeanPostProcessor接口将对Bean进行代理。其流程就是在一个Bean实例化之前,创建代理并替换掉原有Bean。
@Component
public class MyInterfaceClassBeanPostRegister implements BeanPostProcessor, ApplicationContextAware, Ordered {
Map<String, MyInterfaceProcessor> processerMap;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
processerMap = new HashMap<>();
//获取所有自定义的处理过程
Map<String, MyInterfaceProcessor> typeMap = applicationContext.getBeansOfType(MyInterfaceProcessor.class);
for (Map.Entry<String, MyInterfaceProcessor> entry : typeMap.entrySet()) {
MyInterfaceProcessor processor = entry.getValue();
processerMap.put(processor.getType().getSimpleName(), processor);
}
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
//如果没有自定义过程
if(processerMap == null || processerMap.isEmpty())
return bean;
//如果bean实现了接口MyInterface,则通过代理实现自定义增强
if(bean instanceof MyInterface){
List<MyInterfaceProcessor> processors = new ArrayList<>();
//bean实现的接口, 用于确定bean使用的MyInterface
List<Class> interfaces = Arrays.asList(bean.getClass().getInterfaces());
for(Class clazz : interfaces){
if(processerMap.containsKey(clazz.getSimpleName()))
processors.add(processerMap.get(clazz.getSimpleName()));
}
if(processors.isEmpty())
return bean;
//创建InvocationHandler
MyInterfaceInvocationHandler handler = new MyInterfaceInvocationHandler();
handler.setTarget(bean);
handler.setProcessors(processors);
//创建代理
bean = Proxy.newProxyInstance(
bean.getClass().getClassLoader(),
bean.getClass().getInterfaces(),
handler
);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
//优先级靠后,最后再创建代理
@Override
public int getOrder() {
return Integer.MAX_VALUE;
}
}
6、自定义增强接口与处理过程
完成上述内容后,就可以现有基础创建自定义的增强接口。通过继承MyInterface的子接口来标记类,继承MyInterfaceProcessor来处理对应子接口的增强过程。并将MyInterfaceProcessor对象注册到IOC容器中交由Spring管理。
以1个日志接口和计数接口为例。
public interface MyLog extends MyInterface {
}
public interface MyCount extends MyInterface {
}
分别为这两个接口创建增强过程。
@Component
public class MyLogProcessor implements MyInterfaceProcessor<MyLog> {
@Override
public void beforeInvoke(Object target, Method method, Object[] args){
System.out.println("before log:" + target.getClass().getName());
}
@Override
public void afterInvoke(Object target, Method method, Object[] args){
System.out.println("after log:" + target.getClass().getName());
}
@Override
public Class<MyLog> getType() {
return MyLog.class;
}
}
@Component
public class MyCountProcessor implements MyInterfaceProcessor<MyCount> {
private Map<String, Integer> count;
public MyCountProcessor() {
count = new HashMap<>();
}
@Override
public void beforeInvoke(Object target, Method method, Object[] args){
String key = target.getClass().getName().replace(".","") + method.getName();
int i = count.containsKey(key) ? count.get(key) : 0;
System.out.println(target.getClass().getSimpleName() + ","+ method.getName() + ": " + ++i);
count.put(key,i);
}
@Override
public Class<MyCount> getType() {
return MyCount.class;
}
}
7、实现接口
创建一个service类接口
public interface DemoService {
void test1();
void test2();
}
并实现,实现的同时继承自定义的MyInterface接口
@Service
public class DemoServiceImpl implements DemoService, MyLog, MyCount {
public void test1(){
System.out.println("test1");
}
public void test2(){
System.out.println("test2");
}
}
运行结果: