前言
提到对类进行增强,一定会想到动态代理。本文使用两种方法实现对类进行增强。
实现
实现一:后置处理器实现
通过springboot提供的后置处理,生成对应的曾强类进行增强。实现BeanPostProcessor
接口,在postProcessAfterInitialization
生成代理类,对执行方法进行增强。
import com.spring.demo.processor.JdkDynamicAopProxy;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInterceptor;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
import java.lang.reflect.Proxy;
/**
* Bean组件的 PostProcessor;
*/
@Component
@Slf4j
public class MyBeanPostProcessor implements BeanPostProcessor, BeanClassLoaderAware {
private ClassLoader classLoader;
public MyBeanPostProcessor() {
System.out.println("MyBeanPostProcessor...");
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
//前置条件判断 这里模拟只对某些包下的类进行曾强
String className = bean.getClass().getName();
boolean jdkDynamicProxy = AopUtils.isJdkDynamicProxy(bean);
boolean cglibProxy = AopUtils.isCglibProxy(bean);
if (jdkDynamicProxy || cglibProxy) {
Class<?> targetClass = AopUtils.getTargetClass(bean);
className = targetClass.getName();
}
//只对指定包下的类型进行增强
boolean contains = className.contains("com.spring.demo.service");
if (contains) {
//如果是接口则使用jdk动态代理
if (bean.getClass().getInterfaces().length > 0) {
log.info("当前bean为jdk代理:{}", beanName);
//生成代理对象
return Proxy.newProxyInstance(
this.classLoader,
bean.getClass().getInterfaces(), new JdkDynamicAopProxy(bean));
} else { //否则使用cglib代理
log.info("当前bean为cglib代理:{}", beanName);
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(bean);
proxyFactory.addAdvice((MethodInterceptor) invocation -> {
System.out.println("before call real object,cglib dynamic proxy");
Object result = invocation.proceed();
System.out.println("after call real object,cglib dynamic proxy");
return result;
});
return proxyFactory.getProxy();
}
}
return bean;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
}
JdkDynamicAopProxy
public class JdkDynamicAopProxy implements InvocationHandler {
/**
* 目标对象
*/
private Object target;
public JdkDynamicAopProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("-----before call real object,jdk dynamic proxy......");
Object invoke = method.invoke(target, args);
System.out.println("-----after call real object,jdk dynamic proxy");
return invoke;
}
}
实现二:AOP实现
使用aop进行实现。
- 切点实现类
import org.springframework.aop.ClassFilter;
import org.springframework.aop.support.StaticMethodMatcherPointcut;
import java.lang.reflect.Method;
/**
* 切点(Pointcut),按照规则匹配需要代理的方法
*/
@Slf4j
public class CustomPointcut extends StaticMethodMatcherPointcut implements ClassFilter {
@Override
public boolean matches(Class<?> clazz) {
boolean contains = clazz.getName().contains("com.spring.demo.service");
if (contains) {
log.info("CustomPointcut:{}",clazz.getName());
}
return contains;
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
boolean contains = targetClass.getName().contains("com.spring.demo.service");
if (contains) {
log.info("CustomPointcut:{}",targetClass.getName());
}
return contains;
}
}
增强实现类
import org.springframework.aop.Pointcut; import org.springframework.aop.support.AbstractBeanFactoryPointcutAdvisor; public class CustomAdvisor extends AbstractBeanFactoryPointcutAdvisor { @Override public Pointcut getPointcut() { return new CustomPointcut(); } }
拦截器
import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import java.lang.reflect.Method; /** * 拦截器,执行拦截目标方法 */ public class CustomInterceptor implements MethodInterceptor { @Override public Object invoke(MethodInvocation invocation) throws Throwable { Method method = invocation.getMethod(); Object obj = invocation.getThis(); System.out.println("method name:" + method.getName()); System.out.println("obj:" + obj.getClass()); System.out.println("before call real object,cglib dynamic proxy"); Object result = invocation.proceed(); System.out.println("after call real object,cglib dynamic proxy"); return result; } }
配置
@Configuration public class CustomProxyConfig { @Bean public CustomAdvisor customAdvisor(CustomInterceptor customInterceptor) { CustomAdvisor advisor = new CustomAdvisor(); advisor.setAdvice(customInterceptor); return advisor; } @Bean public CustomInterceptor customInterceptor() { return new CustomInterceptor(); } }