静态代理
什么是代理,意思就是你不用去做,别人替你去做。比如说赚钱方面,我就是我老婆的Proxy,带小孩方面,我老婆是我的Proxy.
- 员工的接口,包括有一个工作的方法
package staticproxy;
/**
* @author by benny on 2016/1/2.
* @version 1.0
* @description
*/
public class EmployeeProxy implements Employee {
private Employee employee;
public EmployeeProxy() {
this.employee = new EmployeeImpl();
}
@Override
public void work(String name) {
//方法之前
before();
employee.work(name);
//方法之后
after();
}
public void before(){
System.out.println("准备上班");
}
public void after(){
System.out.println("准备下班");
}
}
- 增加一个雇员的代理类,这样就不用写死在work方法里面了。
package staticproxy;
/**
* @author by benny on 2016/1/2.
* @version 1.0
* @description
*/
public class EmployeeProxy {
private Employee employee;
public EmployeeProxy() {
this.employee = new EmployeeImpl();
}
public void work() {
//方法之前
before();
employee.work("benny");
//方法之后
after();
}
public void before(){
System.out.println("准备上班");
}
public void after(){
System.out.println("准备下班");
}
}
- 测试类
package staticproxy;
/**
* @author by benny on 2016/1/2.
* @version 1.0
* @description 测试雇员的静态代理类
*/
public class EmployeeProxyTest {
public static void main(String[] args) {
Employee proxy = new EmployeeProxy();
proxy.work("benny");
}
}
- 打印测试结果
准备上班
benny正在工作中!
准备下班
动态代理
- JDK动态代理
如果像上面那样每个类增加方法之类的都要写一个代理类的话,那么将会导出都是***Proxy类了,所以将这些Proxy重构为“动态代理”。
- 写一个动态代理类、
package jdkproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* @author by benny on 2016/1/2.
* @version 1.0
* @description
*/
public class DynamicProxy implements InvocationHandler {
private Object obj;
//通过构造器将obj注入
public DynamicProxy(Object obj){
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
//此处需要主次传入的参数 一个是我们注入进来的对象
Object target = method.invoke(obj, args);
after();
return target;
}
public void before() {
System.out.println("准备上班");
}
public void after() {
System.out.println("准备下班");
}
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
}
- 测试类
package jdkproxy;
import java.lang.reflect.Proxy;
/**
* @author by benny on 2016/1/2.
* @version 1.0
* @description
*/
public class DynamicProxyTest {
public static void main(String[] args){
//实例化雇员
Employee employee = new EmployeeImpl();
DynamicProxy proxy = new DynamicProxy(employee);
//此处指定是哪一个接口,这样才能知道调用那个接口里的方法
Employee employeeProxy = (Employee) Proxy.newProxyInstance(
employee.getClass().getClassLoader(),
employee.getClass().getInterfaces(),
proxy);
employeeProxy.work("benny");
}
}
其实动态代理就是帮我们自动生成Xxx代理类的法宝。
需要注意,Proxy.newProxyInstance 方法的参数
Proxy.newProxyInstance(Xxx.getClass().getClassLoader(), Xxx.getClass().getInterfaces(), this);
this 一定是实现了InvocationHandler接口才能有this。
从这个方法里就可以看出,要动态代理的类必须要实现接口才可以使JDK动态代理。
- 参数1:ClassLoader
- 参数2:该实现类的所有接口
- 参数3:动态代理对象
调用完了还要强制转换一下。
- DynamicProxy重构
package jdkproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author by benny on 2016/1/2.
* @version 1.0
* @description
*/
public class DynamicProxy implements InvocationHandler {
private Object obj;
//通过构造器将obj注入
public DynamicProxy(Object obj){
this.obj = obj;
}
-------------------/*增加此方法*/---------------------------
//提取获得动态代理的方法
public <T> T getDynamicProxy(){
return (T) Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
}
-------------------/*增加此方法*/---------------------------
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object target = method.invoke(obj, args);
after();
return target;
}
public void before() {
System.out.println("准备上班");
}
public void after() {
System.out.println("准备下班");
}
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
}
- 测试类
package jdkproxy;
/**
* @author by benny on 2016/1/2.
* @version 1.0
* @description
*/
public class DynamicProxyTest {
public static void main(String[] args){
DynamicProxy dynamicProxy = new DynamicProxy(new Employee());
Employee employeeProxy = dynamicProxy.getDynamicProxy();
employeeProxy.work("benny");
}
}
- CGLIB动态代理
用了DynamicProxy,还是蛮好的,好的地方是,接口变了,这个动态代理类不用变。静态代理就不一样了,接口变了实现类还要变,代理类也要变,JDK动态代理类也不是万能的,比如说代理一个没有任何接口的类,它就无用武之地了。
- 第一步:实现MethodInterceptor接口。
- 第二步:重写intercept方法。Object o = methodProxy.invokeSuper( (被代理的对象)object , args ) ;
- 第三步:获得代理类 getProxy(Class clazz)
return Enhancer.create( clazz , this ) ;
- 动态代理类
package cglib;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* @author by benny on 2016/1/3.
* @version 1.0
* @description
*/
public class CGLibProxy implements MethodInterceptor {
private static CGLibProxy instance = new CGLibProxy();
private CGLibProxy() {
}
public CGLibProxy getCGLibProxy() {
return instance;
}
public <T> T getProxy(Class<T> clazz) {
return (T) Enhancer.create(clazz, this);
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
before();
Object o1 = methodProxy.invokeSuper(o, objects);
after();
return o1;
}
public void before() {
System.out.println("准备上班");
}
public void after() {
System.out.println("准备下班");
}
}
- 测试类
package cglib;
/**
* @author by benny on 2016/1/3.
* @version 1.0
* @description
*/
public class CGLibProxytest {
public static void main(String[] args) {
EmployeeImpl proxy = CGLibProxy.getCGLibProxy().getProxy(EmployeeImpl.class);
proxy.work("benny");
}
}