OverrideMethod,顾名思义,就是将原方法重写。OverrideMethod使用了CGLib动态代理。
Look-up Method 与 Replace Method
Spring的OverrideMethod分为两类:
- Look-up Method:将原方法替换为Spring的getBean()方法
- Replace Method:将原方法替换为任意方法
Look-up Method 是 Replace Method 的子集。
Look-up Method
<bean id="fruitPlate" class="com.xxx.overridemethod.FruitPlate">
<lookup-method bean="apple" name="getFruit"/>
</bean>
<bean id="apple" class="com.xxx.overridemethod.Apple"></bean>
public class FruitPlate {
public Fruit getFruit() {return null;}
}
public interface Fruit{}
public class Apple implement Fruit{}
在这个例子中,我们希望每次调用FruitPlate的getFruit方法,都返回一个新的苹果。因此,Apple是原型的,每次调用getFruit,都通过Spring的getBean方法返回一个新的Apple。
Replace Method
<bean id="fruitPlate" class="com.xxx.overridemethod.FruitPlate">
<replace-method bean="apple" name="getFruit"/>
</bean>
<bean name="getFruit" class="com.xxx.overridemethod.FruitPlateMethodReplacer"> </bean>
public class FruitPlateMethodReplacer implements MethodReplacer {
public Object reimplement(Object obj, Method method, Object[] args) throws Throwable {
return new Apple();
}
}
这个例子中,我们通过FruitPlateMethodReplacer替换getFruit,每次调用getFruit,都手动new一个新的Apple。
CGLib
介绍
CGLIB 原理:动态生成一个要代理类的子类,子类重写要代理的类的所有不是final的方法。在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。它比使用java反射的JDK动态代理要快。
CGLIB 底层:使用字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。
CGLIB 缺点:对于final方法,无法进行代理。
CGLIB(Code Generation Library) 介绍与原理
https://www.runoob.com/w3cnote/cglibcode-generation-library-intro.html
使用示例
拦截器(MethodInterceptor)
public class FruitPlate {
public Fruit getFruit(String fruitName) {return null;}
}
public interface Fruit{}
public class Apple implement Fruit{}
public class GetAppleInterceptor implements MethodInterceptor{
/**
* 重写方法拦截在方法前和方法后加入业务
* Object obj为目标对象
* Method method为目标方法
* Object[] params 为参数,
* MethodProxy proxy CGlib方法代理对象
*/
@Override
public Object intercept(Object obj, Method method, Object[] params,
MethodProxy proxy) throws Throwable {
if (!method.getName().equals("getFruit")) {
throw new UnsupportedOperationException();
}
return new Apple();
}
}
public class TestFruitPlate {
public static void main(String args[]) {
Enhancer enhancer =new Enhancer();
enhancer.setSuperclass(FruitPlate.class);
enhancer.setCallback(new GetAppleInterceptor());
FruitPlate fruitPlate =(FruitPlate)enhancer.create();
System.out.println(fruitPlate.getFruit());
}
}
运行上述代码,在执行fruitPlate.getFruit("apple")
方法时,成功被拦截器拦截,返回Apple对象。
回调过滤器(CallbackFilter)
public class GetAppleInterceptor implements MethodInterceptor{
@Override
public Object intercept(Object obj, Method method, Object[] params,
MethodProxy proxy) throws Throwable {
if (!method.getName().equals("getFruit")) {
throw new UnsupportedOperationException();
}
return new Apple();
}
}
public class GetBananaInterceptor implements MethodInterceptor{
@Override
public Object intercept(Object obj, Method method, Object[] params,
MethodProxy proxy) throws Throwable {
if (!method.getName().equals("getFruit")) {
throw new UnsupportedOperationException();
}
return new Banana();
}
}
public class GetFruitTypeCallbackFilter implements CallbackFilter {
/**
* 过滤方法
* 返回的值为数字,代表了Callback数组中的索引位置,要到用的Callback
*/
@Override
public int accept(Method method) {
if(!method.getName().equals("getFruit")){
return 0;
}
int fruitType = (int) (Math.random() * 2)
switch(fruitType) {
case 0:
return 1;
case 1:
return 2;
}
return 0;
}
}
public class TestCglib {
public static void main(String args[]) {
Enhancer enhancer =new Enhancer();
enhancer.setSuperclass(FruitPlate.class);
CallbackFilter callbackFilter = new GetFruitTypeCallbackFilter();
/**
*
(1)NoOp.INSTANCE:这个NoOp表示no operator,即什么操作也不做,代理类直接调用被代理的方法不进行拦截。
(2)FixedValue:表示锁定方法返回值,无论被代理类的方法返回什么值,回调方法都返回固定值。
(3)callback1:方法拦截器
*/
Callback noopCb=NoOp.INSTANCE;
Callback appleCallback=new GetAppleInterceptor();
Callback bananaCallback=new GetBananaInterceptor();
Callback[] cbarray=new Callback[]{noopCb, appleCallback, bananaCallback};
enhancer.setCallbacks(cbarray);
enhancer.setCallbackFilter(callbackFilter);
FruitPlate fruitPlate =(FruitPlate)enhancer.create();
System.out.println(fruitPlate.getFruit());
System.out.println(fruitPlate.getFruit());
System.out.println(fruitPlate.getFruit());
System.out.println(fruitPlate.getFruit());
}
}
运行上述代码,执行fruitPlate.getFruit()
时,回调过滤器使用随机的方式,返回下标1或2,再根据下标调用GetAppleInterceptor或GetBananaInterceptor,返回Apple或Banana。
源码分析
Spring的Bean创建过程中,会检测BeanDefinition是否存在OverrideMethod,如果存在,则会在实例化使使用CGLib进行代理。
CGLib实例化过程
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
if (bd.getMethodOverrides().isEmpty()) {
...
}
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
private static class CglibSubclassCreator {
private static final Class<?>[] CALLBACK_TYPES = new Class<?>[]
{NoOp.class, LookupOverrideMethodInterceptor.class, ReplaceOverrideMethodInterceptor.class};
private final RootBeanDefinition beanDefinition;
private final BeanFactory owner;
CglibSubclassCreator(RootBeanDefinition beanDefinition, BeanFactory owner) {
this.beanDefinition = beanDefinition;
this.owner = owner;
}
/**
* Create a new instance of a dynamically generated subclass implementing the
* required lookups.
* @param ctor constructor to use. If this is {@code null}, use the
* no-arg constructor (no parameterization, or Setter Injection)
* @param args arguments to use for the constructor.
* Ignored if the {@code ctor} parameter is {@code null}.
* @return new instance of the dynamically generated subclass
*/
public Object instantiate(Constructor<?> ctor, Object... args) {
Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
Object instance;
// 省略subclass实例化为instance过程
...
return instance;
}
/**
* Create an enhanced subclass of the bean class for the provided bean
* definition, using CGLIB.
*/
// 创建CGLib子类
private Class<?> createEnhancedSubclass(RootBeanDefinition beanDefinition) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(beanDefinition.getBeanClass());
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
...
// CallbackFilter
enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition));
// 拦截器
enhancer.setCallbackTypes(CALLBACK_TYPES);
return enhancer.createClass();
}
}
CallbackFilter
/**
* CGLIB callback for filtering method interception behavior.
*/
private static class MethodOverrideCallbackFilter extends CglibIdentitySupport implements CallbackFilter {
public MethodOverrideCallbackFilter(RootBeanDefinition beanDefinition) {
super(beanDefinition);
}
@Override
public int accept(Method method) {
MethodOverride methodOverride = getBeanDefinition().getMethodOverrides()
.getOverride(method);
// 如果该方法没被覆盖,返回下标0
if (methodOverride == null) {
return PASSTHROUGH;
}
// 如果该方法被LookupOverride覆盖,返回下标1
else if (methodOverride instanceof LookupOverride) {
return LOOKUP_OVERRIDE;
}
// 如果该方法被ReplaceOverride覆盖,返回下标2
else if (methodOverride instanceof ReplaceOverride) {
return METHOD_REPLACER;
}
// 如果都不是,抛出异常
throw new UnsupportedOperationException("Unexpected MethodOverride subclass: " +
methodOverride.getClass().getName());
}
}
MethodInterceptor
LookupOverrideMethodInterceptor
/**
* CGLIB MethodInterceptor to override methods, replacing them with an
* implementation that returns a bean looked up in the container.
*/
private static class LookupOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor {
private final BeanFactory owner;
public LookupOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanFactory owner) {
super(beanDefinition);
this.owner = owner;
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
// Cast is safe, as CallbackFilter filters are used selectively.
// 获取BD中的lookup-method信息
LookupOverride lo = (LookupOverride) getBeanDefinition().getMethodOverrides().getOverride(method);
Object[] argsToUse = (args.length > 0 ? args : null); // if no-arg, don't insist on args at all
// 如果指定了name属性,就getBeanByName
if (StringUtils.hasText(lo.getBeanName())) {
return this.owner.getBean(lo.getBeanName(), argsToUse);
}
// 否则,getBeanByType
else {
return this.owner.getBean(method.getReturnType(), argsToUse);
}
}
}
ReplaceOverrideMethodInterceptor
/**
* CGLIB MethodInterceptor to override methods, replacing them with a call
* to a generic MethodReplacer.
*/
private static class ReplaceOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor {
private final BeanFactory owner;
public ReplaceOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanFactory owner) {
super(beanDefinition);
this.owner = owner;
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
// 获取BD中的replace-method信息
ReplaceOverride ro = (ReplaceOverride) getBeanDefinition().getMethodOverrides().getOverride(method);
// TODO could cache if a singleton for minor performance optimization
// 获取对应的 MethodReplacer Bean对象
MethodReplacer mr = this.owner.getBean(ro.getMethodReplacerBeanName(), MethodReplacer.class);
// 执行reimplement方法
return mr.reimplement(obj, method, args);
}
}