代理
代理的作用:对具有通用功能的方法进行增强。(把通用功能部分拿出来经行代理)
静态代理
package demo01;
/**
* 静态代理,对现有的方法进行增强
*
*/
public class TestStaticProxy {
public static void main(String[] args) {
Human man = new Human("情迷");
MarryCompany marryCompany = new MarryCompany(man);
marryCompany.getMarry();
}
}
interface Marry {
/**
* 结婚接口
*/
void getMarry();
}
class Human implements Marry{
String name;
public Human(String name) {
this.name = name;
}
public void getMarry() {
System.out.println(this.name + "要结婚啦!!!");
}
}
class MarryCompany implements Marry{
private Human targetMan;
public MarryCompany(Human targetMan) {
this.targetMan = targetMan;
}
public void getMarry() {
before();
targetMan.getMarry();
after();
}
private void before(){
/**
* 前置通知
*/
System.out.println("预订酒店,值班场地!");
System.out.println("推送婚车,迎接新娘!");
System.out.println("专业司仪,致祝福语!");
}
private void after(){
/**
* 后置通知
*/
System.out.println("打扫场地,收取费用!");
}
}
预订酒店,值班场地!
推送婚车,迎接新娘!
专业司仪,致祝福语!
情迷要结婚啦!!!
打扫场地,收取费用!
以上代码解决了对结婚方法的增强,但是未解决通用行,只能对Human进行代理,而不能对其他类的对象进行代理,解决办法,我们对代理类进行修改一下:
前面的代码是对类的代理,现在改为对Marry接口的代理,一样完成了代理,并且使得代理对象具有了通用性,代理类只需实现Marry接口,就可使用代理类。
class MarryCompany implements Marry{
private Marry targetMan;
public MarryCompany(Marry targetMan) {
this.targetMan = targetMan;
}
public void getMarry() {
before();
targetMan.getMarry();
after();
}
private void before(){
/**
* 前置通知
*/
System.out.println("预订酒店,值班场地!");
System.out.println("推送婚车,迎接新娘!");
System.out.println("专业司仪,致祝福语!");
}
private void after(){
/**
* 后置通知
*/
System.out.println("打扫场地,收取费用!");
}
}
动态代理
静态代理局限性:只能对某一个接口中的一个方法经行代理,接口每增加一个方法,就要对新增的方法增加一个代理方法。对于不同的类或者接口,里面不同的通用方法,也要写相同数量的代理方法。此时用动态代理:
InvocationHandle
package demo02.services;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class TestMarry {
private Object object;
public TestMarry(Object object){
this.object = object;
}
public TestMarry() {
}
private void before(){
System.out.println("before");
}
private void after(){
System.out.println("after");
}
/**
* 动态代理方法
* @return Object
*/
public Object proxy(){
return Proxy.newProxyInstance(object.getClass().getClassLoader(),
object.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object invoke = method.invoke(object, args);
after();
return invoke;
}
});
}
}
package demo02.services;
import demo02.IMarry;
import demo02.impl.Marry;
public class TestProxy {
public static void main(String[] args) {
final IMarry human = new Marry();
TestMarry testMarry = new TestMarry(human);
IMarry proxy = (IMarry) testMarry.proxy();
proxy.marry();
proxy.cutMarr();
}
}
代理类接收Object对象,对其两个方法经行代理。
cglib代理 (第三方)
在动态代理的方法中,有一个参数是获取代理对象的类实现的接口,那么对于没有实现接口的类,就无法进行动态代理。所以使用cglib进行代理。
package cglibProxy;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class TestCglib implements MethodInterceptor {
private Object object;
public TestCglib(Object o) {
this.object = o;
}
//给目标对象创建一个代理对象
public Object getProxyInstance(){
//1.cglib工具类
Enhancer en = new Enhancer();
//2.设置父类
en.setSuperclass(object.getClass());
//3.设置回调函数
en.setCallback(this);
//4.创建子类(代理对象)
return en.create();
}
/**
* 代理方法
* @param o
* @param method
* @param objects
* @param methodProxy
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before");
Object o1 = methodProxy.invoke(object, objects);
System.out.println("after");
return o1;
}
}
package cglibProxy;
import demo02.IMarry;
import demo02.impl.Marry;
public class CglibProxy extends Thread {
@Override
public void run() {
System.out.println("runging");
}
public static void main(String[] args) {
TestCglib testCglib = new TestCglib(new Marry().setName("xiaolu"));
IMarry proxyInstance = (Marry) testCglib.getProxyInstance();
proxyInstance.marry();
proxyInstance.cutMarr();
}
}
TestCglib testCglib = new TestCglib(new Marry().setName(“xiaolu”));只能传类,不能是接口
这样就解决了没有实现接口的类不能代理的问题