静态代理和动态代理区别:
我们根据加载被代理类的时机不同,将代理分为静态代理和动态代理。①如果我们在代码编译时就确定了被代理的类是哪一个,那么就可以直接使用静态代理;②如果不能确定,那么可以使用类的动态加载机制,在代码运行期间加载被代理的类这就是动态代理,比如RPC框架和Spring AOP机制。
代理的优点是在不改变这个方法的前提下去丰富他。这样老功能试用原来的方法也不会有问题,新功能通过代理丰富了原来的方法被广泛试用。
动态代理
新建一个开发者接口,开发者他会开发code,他会调试debug
public interface Developer {
void code();
void debug();
}
新建一个java开发者来实现开发者接口里的code、debug方法
@Data
public class JavaDeveloper implements Developer {
String name;
public JavaDeveloper(String name) {
this.name = name;
}
@Override
public void code(){
System.out.println("a code man");
}
@Override
public void debug(){
System.out.println("a debug man");
}
}
进行动态代理使用java开发者开发项目
@RunWith(SpringRunner.class)
@SpringBootTest(classes = AdminApplication.class)
public class ProxyTest {
@Test
public void NoProxyTest(){
JavaDeveloper Jack = new JavaDeveloper("Jack");
Jack.code();
Jack.debug();
//打印结果
// a code man
// a debug man
}
@Test
public void ProxyTest(){
JavaDeveloper Jack = new JavaDeveloper("Jack");
Developer jackProxy = (Developer) Proxy.newProxyInstance(
Jack.getClass().getClassLoader(),
Jack.getClass().getInterfaces(),
(proxy, method, args) -> {
if (method.getName().equals("code")){
System.out.println("Jack proxy code!!");
method.invoke(Jack, args);
}
if (method.getName().equals("debug")){
System.out.println("Jack proxy debug!!");
return null;
}
return null;
});
jackProxy.code();
jackProxy.debug();
//打印结果
// Jack proxy code!!
// a code man
// Jack proxy debug!!
}
}
刚开始把Developer写成了类,JavaDeveloper继承。报错如下:
java.lang.ClassCastException: com.sun.proxy.$Proxy12 cannot be cast to Developer
原因:
对于Spring AOP 采用两种代理方法,一种是常规JDK,一种是CGLIB,当代理对象实现了至少一个接口时,默认使用JDK动态创建代理对象,当代理对象没有实现任何接口时,就会使用CGLIB方法。
解决方法:
Java api代理机制求被代理类必须要实现某个接口。将代理对象转换成接口。
静态代理
写一个知道代理类的静态代理实现类
public class StaticProxyTest implements Developer{
JavaDeveloper javaDeveloper;
public StaticProxyTest(JavaDeveloper javaDeveloper) {
this.javaDeveloper = javaDeveloper;
}
@Override
public void code() {
System.out.println("ProxyTest sayHello begin");
//在代理类的方法中 间接访问被代理对象的方法
javaDeveloper.code();
System.out.println("ProxyTest sayHello end");
}
@Override
public void debug() {
System.out.println("ProxyTest sayHello begin");
//在代理类的方法中 间接访问被代理对象的方法
javaDeveloper.debug();
System.out.println("ProxyTest sayHello end");
}
}
@Test
public void staticProxyTest(){
JavaDeveloper javaDeveloper = new JavaDeveloper("Jack");
StaticProxyTest proxyTest = new StaticProxyTest(javaDeveloper);
proxyTest.code();
proxyTest.debug();
}
//打印
// ProxyTest sayHello begin
// a code man
// ProxyTest sayHello end
// ProxyTest sayHello begin
// a debug man
// ProxyTest sayHello end