一 java原生动态代理。
- 定义一个接口 Animal
public interface Animal {
String getName();
}
- 定义一个 类实现InvocationHandler
public class ProxyAnimal implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return "dog";
}
}
- 开始测试。
public class Test {
@org.junit.Test
public void testProxyAnimal() {
ProxyAnimal proxyAnimal = new ProxyAnimal();
ClassLoader loader = Test.class.getClassLoader();
Animal animal = (Animal)Proxy.newProxyInstance(loader, new Class[]{Animal.class}, proxyAnimal);
System.out.println(animal.getName());
}
}
测试结束。
这里留有1个问题
1 为什么一定要定义接口。如果不定义接口的话会异常
java.lang.IllegalArgumentException: zyk.test.proxy3.Cat is not an interface
二 场景简单模拟。
动态代理有什么用,动态代理的原理就是写一段代码块,从而实现增强的效果。这里设置一个场景,例如 统计 所有实现Animal 方法的类的方法调用时间。
如果不用动态代理可能是这样的
public interface Animal {
String getName();
void eatSomething(String food);
}
public class Cat implements Animal {
Logger logger = LoggerFactory.getLogger(Animal.class);
@Override
public String getName() {
return "cat";
}
@Override
public void eatSomething(String food) {
logger.info("cat is eat " +food);
}
}
public class Dog implements Animal {
Logger logger = LoggerFactory.getLogger(Animal.class);
@Override
public String getName() {
return "dog";
}
@Override
public void eatSomething(String food) {
logger.info("dog is eat " +food);
}
}
@org.junit.Test public void testAnimal() {
Animal animal = new Cat();
logger.info(animal.getName());
animal.eatSomething(" fish");
}
重点来了 应 动物管理协会的规定,所有小动物进食前都需要 喝一碗汤。
代码需要变成这样,每个实现类都需要加一个喝汤的逻辑。
public class Dog implements Animal {
Logger logger = LoggerFactory.getLogger(Animal.class);
@Override
public String getName() {
return "dog";
}
@Override
public void eatSomething(String food) {
logger.info("喝汤");
logger.info("dog is eat " +food);
}
}
public class Cat implements Animal {
Logger logger = LoggerFactory.getLogger(Animal.class);
@Override
public String getName() {
return "cat";
}
@Override
public void eatSomething(String food) {
logger.info("喝汤");
logger.info("cat is eat " +food);
}
}
如果使用动态代理的话可以优化为这样。
public interface Animal {
String getName();
void eatSomething(String food);
}
public class Cat implements Animal {
Logger logger = LoggerFactory.getLogger(Animal.class);
@Override
public String getName() {
return "cat";
}
@Override
public void eatSomething(String food) {
logger.info("cat is eat " +food);
}
}
public class Dog implements Animal {
Logger logger = LoggerFactory.getLogger(Animal.class);
@Override
public String getName() {
return "dog";
}
@Override
public void eatSomething(String food) {
logger.info("dog is eat " +food);
}
}
public class ProxyAnimal implements InvocationHandler {
Logger logger = LoggerFactory.getLogger(Animal.class);
private Animal animal;
public ProxyAnimal(Animal animal) {
this.animal = animal;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (("eatSomething").equals(method.getName())){
logger.info("喝汤");
}
return method.invoke(animal,args);
}
}
Logger logger = LoggerFactory.getLogger(Test.class);
@org.junit.Test public void testProxyAnimal() {
ProxyAnimal proxyAnimal = new ProxyAnimal(new Cat());
ClassLoader loader = Test.class.getClassLoader();
Animal animal = (Animal)Proxy.newProxyInstance(loader, new Class[]{Animal.class}, proxyAnimal);
logger.info(animal.getName());
animal.eatSomething("fish");
}
这样所有的eatSomething 方法都加上了喝汤的方法。