面试题:被final修饰的类可以被spring代理吗?
来自社群的两个面试题,其实也是两个基础的 面试题,大家一定要掌握
社群问题:
结论
场景1:
如果委托类没有实现接口的话,就不能使用newProxyInstance方法,进而不能使用JDK动态代理
场景2:
Cglib是针对类来实现代理的,对指定的目标类生成一个子类,通过方法拦截技术拦截所有父类方法的调用。因为是生成子类,所以就不能用在final修饰的类上。
综合起来,就是 被final修饰的类 ,不可以被spring代理
参考代码:
public interface Foo {
void bar();
}
public class FooInvocationHandler implements InvocationHandler {
Object target = null;
public FooInvocationHandler(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("method :" + method.getName() + " is invoked!");
return method.invoke(target, args); // 执行相应的目标方法
}
}
/**
* 动态代理测试
*/
@Test
public void simpleDynamicProxyTest() {
try {
// 这里有两种写法,采用复杂的一种写法,有助于理解。
Class<?> proxyClass = Proxy.getProxyClass(FooInvocationHandler.class.getClassLoader(), Foo.class);
final Constructor<?> cons;
cons = proxyClass.getConstructor(InvocationHandler.class);
final InvocationHandler ih = new FooInvocationHandler(new Foo() {
@Override
public void bar() {
System.out.println("匿名的 br is invoked!");
}
});
Foo foo = (Foo) cons.newInstance(ih);
foo.bar();
// 下面是简单的一种写法,本质上和上面是一样的
/*
HelloWorld helloWorld=(HelloWorld)Proxy.
newProxyInstance(JDKProxyTest.class.getClassLoader(),
new Class<?>[]{HelloWorld.class},
new MyInvocationHandler(new HelloworldImpl()));
helloWorld.sayHello();
*/
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 动态代理测试
*/
@Test
public void simpleDynamicProxyTest2() {
try {
FooInvocationHandler handler = new FooInvocationHandler(new Foo() {
@Override
public void bar() {
System.out.println("匿名的 br is invoked!");
}
});
// 这里有两种写法,采用复杂的一种简单写法,对比上面的写法,有助于理解。
Foo foo = (Foo) Proxy.newProxyInstance(FooInvocationHandler.class.getClassLoader(),
new Class<?>[]{Foo.class}, handler);
foo.bar();
} catch (Exception e) {
e.printStackTrace();
}
}
// 面试题:被final修饰的类可以被spring代理吗?
public final class FinalFoo {
void bar(){
System.out.println("final class FinalFoo 的 bar 方法 is invoked!");
}
}
public class FinalFooInvocationHandler implements InvocationHandler {
FinalFoo target = null;
public FinalFooInvocationHandler(FinalFoo target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("method :" + method.getName() + " is invoked!");
return method.invoke(target, args); // 执行相应的目标方法
}
}
/**
* 动态代理测试
*/
@Test
public void simpleDynamicProxyTest3() {
try {
FinalFooInvocationHandler handler = new FinalFooInvocationHandler(new FinalFoo());
// 面试题:被final修饰的类可以被spring代理吗?
FinalFoo foo = (FinalFoo) Proxy.newProxyInstance(FooInvocationHandler.class.getClassLoader(),
new Class<?>[]{FinalFoo.class}, handler);
foo.bar();
} catch (Exception e) {
e.printStackTrace();
}
}