作用:通过代理可以控制访问某个对象的方法,在调用这个方法前做前置处理,调用这个方法后做后置处理。(即: AOP的微观实现!)
核心角色
抽象角色(接口):定义公共对外方法
真实角色(周杰伦):实现抽象角色,定义真实角色所要实现的业务逻辑,
代理角色(代理人):实现抽象角色,是真实角色的代理,通过调用真实角色的方法来完成业务逻辑,并可以附加自己的操作
package com.by.proxy.staticProxy;
public interface Star {
/**
* 面谈
*/
void confer();
/**
* 签合同
*/
void signContract();
/**
* 订票
*/
void bookTicket();
/**
* 唱歌
*/
void sing();
/**
* 收钱
*/
void collectMoney();
}
package com.by.proxy.staticProxy;
public class RealStar implements Star{
@Override
public void confer() {
}
@Override
public void signContract() {
}
@Override
public void bookTicket() {
}
@Override
public void sing() {
System.out.println("天青色等烟雨,而我在等你,炊烟袅袅升起,隔江千万里....");
}
@Override
public void collectMoney() {
}
}
package com.by.proxy.staticProxy;
public class proxyStar implements Star{
private Star star;
public proxyStar(Star star) {
this.star = star;
}
@Override
public void confer() {
System.out.println("面谈");
}
@Override
public void signContract() {
System.out.println("签合同");
}
@Override
public void bookTicket() {
System.out.println("订机票");
}
@Override
public void sing() {
star.sing();
}
@Override
public void collectMoney() {
System.out.println("收尾款");
}
}
package com.by.proxy.staticProxy;
public class Client {
public static void main(String[] args) {
Star star = new proxyStar(new RealStar());
star.sing();
star.bookTicket();
star.collectMoney();
star.confer();
star.signContract();
}
}
代理类和实现类实现了相同的接口,这样就出现了大量的代码重复。
代理对象只服务于一种类型的对象。如果要服务多类型的对象,例如代码是只为UserService类的访问提供了代理,但是还要为其他类如DeptService类提供代理的话,就需要我们再次添加代理DeptService的代理类
package com.by.proxy.jdkProxy;
public interface Star {
void sing();
}
package com.by.proxy.jdkProxy;
public class RealStar implements Star{
@Override
public void sing() {
System.out.println("天青色等烟雨,而我在等你,炊烟袅袅升起,隔江千万里......");
}
}
package com.by.proxy.jdkProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyFactory {
/**
* 要代理的真实角色
*/
private Object realObj;
public ProxyFactory(Object realObj){
this.realObj=realObj;
}
//创建代理工厂,生成代理类proxy{.面谈.签合同.订机票【调用杰哥唱歌】.收尾款}
public Object getObjectProxy(){
/**
* ClassLoader loader,类加载器
* Class>[] interfaces,公共接口
* InvocationHandler h)调用invoke方法
*/
return Proxy.newProxyInstance(realObj.getClass().getClassLoader(),
realObj.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//代理类既要调用真实角色,还要处理自己的事务
System.out.println("面谈");
System.out.println("签合同");
System.out.println("订机票");
Object result = method.invoke(realObj, args);
System.out.println("收尾款");
return result;
}
});
}
}
package com.by.proxy.jdkProxy;
public class Client {
public static void main(String[] args) {
Star star = (Star) new ProxyFactory(new RealStar()).getObjectProxy();
star.sing();
}
}
cglib与动态代理最大的区别就是:
使用jdk动态代理的对象必须实现一个接口
使用cglib代理的对象则无需实现接口
CGLIB是第三方提供的包,所以需要引入jar包的坐标:
cglib
cglib
2.2.2
如果你已经有spring-core的jar包,则无需引入,因为spring中包含了cglib。
package com.by.proxy.CglibProxy;
public class RealStar{
public void sing() {
System.out.println("RealStar(周杰伦本人).sing()");
}
}
package com.by.proxy.CglibProxy;
//测试类
public class Client {
public static void main(String[] args) {
//获取代理对象
RealStar proxyObject =
(RealStar) new ProxyFactory(new RealStar()).getProxyObject();
proxyObject.sing();
}
}
1)静态代理
角色:
公共接口:Star
真实角色:RealStar(真实角色.唱歌)
代理角色:ProxyStar(代理角色.面谈.订机票.签合同.[调周杰伦唱歌].收尾款)
客户类:Client(客户.调代理角色)
缺陷:1.大量代码重复 2.只能代理Star类型的对象
2)jdk动态代理
角色:
公共接口:Star
真实角色:RealStar(真实角色.唱歌)
代理工厂:ProxyFactroy{生成ProxyStar(代理角色.面谈.订机票.签合同.[调周杰伦唱歌].收尾款)}
客户类:Client(客户.调代理角色)
3)Cglib动态代理
cglib和jdk动态代理的区别:cglib真实角色没有接口