java 的动态代理
什么是代理?代理模式就是在原有的服务上多加了一个占卫,通过这个占卫去控制服务的访问。
动态代理示意图如下:
使用动态代理的原因:
1.一方面可以控制如何访问真正的对象,提供额外的服务;
2.另一方面可以重写一些类来满足特定的需要
一般动态代理分为两种:1.jdk反射机制提供的代理 2.cglib提供的代理
反射技术
/**
* java 反射测试
* @author cp
*
*/
public class ReflectService {
public void sayHello(String name) {
System.out.println("hello" + name);
}
public static void main(String[] args) throws InstantiationException,
IllegalAccessException, ClassNotFoundException,
NoSuchMethodException, SecurityException, IllegalArgumentException,
InvocationTargetException {
Object service = Class.forName(ReflectService.class.getName())
.newInstance();
Method method = service.getClass().getMethod("sayHello", String.class);
method.invoke(service, "小鹏要逆袭");
}
}
运行结果:
jdk动态代理技术
jdk的动态代理,是由java.lang.reflect.*包来提供的,我们需要完成几个步骤
1.编写服务类和接口,作为真正的服务提供者(jdk代理中必须)
2.编写代理类,提供绑定和代理的方法
a.创建HelloService类
package com.xiaopeng.test;
public interface HelloService {
public void sayHello(String name);
}
b.创建HelloServiceImpl类实现了HelloService接口
package com.xiaopeng.test;
public class HelloServiceImpl implements HelloService {
@Override
public void sayHello(String name) {
System.out.println("Hello"+name);
}
}
c.创建jdk的动态代理类,实现InvocationHandler
package com.xiaopeng.test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class HelloServiceProxy implements InvocationHandler {
/**
* 真实的对象
*/
private Object target;
/**
* 绑定真实的对象
* @param target
* @return
*/
public Object bind(Object target){
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("===========这是JDK动态代理=========");
Object result = null;
System.out.println("我准备说hello");
result = method.invoke(target, args);
System.out.println("我说过hello了");
return result;
}
}
d.单元测试
@Test
public void testDemo03(){
// 创建服务的动态代理对象
HelloServiceProxy helloServiceProxy = new HelloServiceProxy();
HelloService proxyService = (HelloService) helloServiceProxy.bind(new HelloServiceImpl());
proxyService.sayHello("小鹏要逆袭");
}
e.运行结果截图:
CGLIB动态代理
jdk提供的动态代理有一个缺陷,就是必须要提供接口才可以使用。为了克服这个问题,我们使用CGLIB动态代理。
需要导入的包:
a.创建cglib动态代理对象的类,实现MethodInterceptor接口
package com.xiaopeng.test;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class HelloServiceCGLIB implements MethodInterceptor {
private Object target;
public Object getInstance(Object target){
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("============我是cglib的动态代理===========");
System.out.println("我准备说hello");
Object returnObject = proxy.invokeSuper(obj, args);
System.out.println("我说过hello了");
return returnObject;
}
}
b.单元测试
@Test
public void testDemo04(){
HelloServiceCGLIB helloServiceCGLIB = new HelloServiceCGLIB();
HelloService proxyService = (HelloService) helloServiceCGLIB.getInstance(new HelloServiceImpl());
proxyService.sayHello("hdasl");
}
c.运行结果