1、静态代理
还有一种是继承的方式,代理类直接继承目标类(被代理类),重写需要增强的方法
目标类和代理类实现同一接口,代理对象中包含目标对象
/**
* 静态代理:
* 对一个新的接口需要创建新的代理类 和 被代理类
*/
public class ProxyTest1 {
public static void main(String[] args) {
NikeClothFactory nike = new NikeClothFactory();//创建被代理类的对象
ProxyFactory proxy = new ProxyFactory(nike);//创建代理类的对象
proxy.productCloth();
}
}
/**
* 接口
*/
interface ClothFactory{
void productCloth();
}
/**
* 被代理类
*/
class NikeClothFactory implements ClothFactory{
@Override
public void productCloth() {
System.out.println("Nike工厂生产一批衣服");
}
}
/**
* 代理类
*/
class ProxyFactory implements ClothFactory{
private ClothFactory cf;
//创建代理类的对象时,实际传入一个被代理类的对象
ProxyFactory(ClothFactory cf){
this.cf = cf;
}
@Override
public void productCloth() {
System.out.println("代理类开始执行,收代理费$1000");
cf.productCloth();
}
}
执行main方法:
代理类开始执行,收代理费$1000
Nike工厂生产一批衣服
2、JDK动态代理
/**
* 动态代理
*/
public class ProxyTest2 {
public static void main(String[] args) {
//1.被代理类的对象
RealSubject real = new RealSubject();
//2.创建一个实现了InvocationHandler接口的类的对象
MyInvocationHandler handler = new MyInvocationHandler();
//3.调用blind()方法,动态的返回一个同样实现了real所在类实现的接口Subject的代理类的对象。
Object obj = handler.blind(real);
Subject sub = (Subject)obj;//此时sub就是代理类的对象
sub.action();//转到对InvocationHandler接口的实现类的invoke()方法的调用
//再举一例
NikeClothFactory nike = new NikeClothFactory();
ClothFactory proxyCloth = (ClothFactory)handler.blind(nike);//proxyCloth即为代理类的对象
proxyCloth.productCloth();
}
}
interface Subject {
void action();
}
// 被代理类
class RealSubject implements Subject {
public void action() {
System.out.println("被代理类正在被执行...");
}
}
class MyInvocationHandler implements InvocationHandler {
private Object obj;// 实现了接口的被代理类的对象的声明,真实对象
public Object blind(Object obj) {
// ① 给被代理的对象实例化
this.obj = obj;
// ② 返回一个代理类的对象
/**
* Proxy.newProxyInstance()的三个参数:
* 1、obj.getClass().getClassLoader() 使用和被代理类相同的类加载器
* 2、obj.getClass().getInterfaces() 实现和被代理类相同的接口
* 3、this 实现了InvocationHandler接口的对象,即MyInvocationHandler用this来代替
*/
return Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
this);
}
// 当通过代理类的对象发起对被代理类方法的调用时,都会转换为对如下的invoke方法的调用
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//method方法的返回值时returnVal
return method.invoke(obj, args);
}
执行main方法:
被代理类正在被执行...
Nike工厂生产一批衣服
}
获取指定的被代理类对象,对被代理类对象的方法进行增强
public interface IEat {
void breakfast();
void lunch();
void dinner();
}
public class Eat implements IEat {
@Override
public void breakfast() {
System.out.println("吃早饭!");
}
@Override
public void lunch() {
System.out.println("吃午饭!");
}
@Override
public void dinner() {
System.out.println("吃晚饭!");
}
}
public class Wash {
public void washHands(){
System.out.println("吃饭之前洗手。。。。");
}
public void washDishes(){
System.out.println("吃完饭洗盘子。。。。");
}
}
public class ProxyEat {
private final Eat eat = new Eat();
private Wash wash = new Wash();
public IEat getProxyEat(){
return (IEat) Proxy.newProxyInstance(
eat.getClass().getClassLoader(),
eat.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
wash.washHands();
Object invoke = method.invoke(eat, args);
wash.washDishes();
return invoke;
}
}
);
}
}
public class ProxyTest {
public static void main(String[] args) {
System.out.println("==========被代理类执行吃饭========");
Eat eat = new Eat();
eat.breakfast();
eat.lunch();
eat.dinner();
System.out.println("==========代理类执行吃饭=========");
ProxyEat proxyEat = new ProxyEat();
IEat newEat = proxyEat.getProxyEat();
newEat.breakfast();
newEat.lunch();
newEat.dinner();
}
}
==========被代理类执行吃饭========
吃早饭!
吃午饭!
吃晚饭!
==========代理类执行吃饭=========
吃饭之前洗手。。。。
吃早饭!
吃完饭洗盘子。。。。
吃饭之前洗手。。。。
吃午饭!
吃完饭洗盘子。。。。
吃饭之前洗手。。。。
吃晚饭!
吃完饭洗盘子。。。。
实现对任意被代理类对象方法的增强
public interface Human {
void info();
void work();
}
public class IronMan implements Human{
@Override
public void info() {
System.out.println("我是一个钢铁侠");
}
@Override
public void work() {
System.out.println("钢铁侠开炮了");
}
}
public class SuperMan implements Human{
@Override
public void info() {
System.out.println("我是一个超人");
}
@Override
public void work() {
System.out.println("超人穿上了红内裤");
}
}
public class Actor {
public void present(){
System.out.println("演员出场了");
}
public void exit(){
System.out.println("演员下班了");
}
}
public class MyInvocationHandler implements InvocationHandler {
//声明被代理类对象
private Object object;
public void setObject(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Actor actor = new Actor();
actor.present();
Object value = method.invoke(object, args);
actor.exit();
return value;
}
}
public class ProxyFactory {
public static Object getProxyInstance(Object object){
MyInvocationHandler handler = new MyInvocationHandler();
handler.setObject(object);
return Proxy.newProxyInstance(
object.getClass().getClassLoader(),
object.getClass().getInterfaces(),
handler
);
}
}
public class TestAOP {
@Test
public void test1(){
SuperMan superMan = new SuperMan();
Human human = (Human)ProxyFactory.getProxyInstance(superMan);
human.info();
System.out.println();
human.work();
}
@Test
public void test2(){
IronMan ironMan = new IronMan();
Human human = (Human)ProxyFactory.getProxyInstance(ironMan);
human.info();
System.out.println();
human.work();
}
}
输出
输出:test1() test2()
演员出场了 演员出场了
我是一个超人 我是一个钢铁侠
演员下班了 演员下班了
演员出场了 演员出场了
超人穿上了红内裤 钢铁侠开炮了
演员下班了 演员下班了
CGLIB动态代理
<dependencies>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.1_3</version>
</dependency>
</dependencies>
public class Producer {
/**
* 销售
* @param money
*/
public void saleProduct(float money){
System.out.println("厂家销售产品,并拿到钱:" + money);
}
/**
* 售后
* @param money
*/
public void afterService(float money){
System.out.println("厂家提供售后服务,并拿到钱:" + money);
}
}
/**
* @auther Mr.Liao
*
* 动态代理:
* 特点:字节码随用随创建,随用随加载
* 作用:不修改源码的基础上对方法增强
* 分类:
* 基于接口的动态代理
* 基于子类的动态代理
* 基于子类的动态代理:
* 涉及的类:Enhancer
* 提供者:第三方cglib库
* 如何创建代理对象:
* 使用Enhancer类中的create方法
* 创建代理对象的要求:
* 被代理类不能是最终类
* create方法的参数:
* 1、Class:字节码,它是用于指定被代理对象的字节码。
* 2、Callback:用于提供增强的代码
* 它是让我们写如何代理。我们一般都是些一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的。
* 此接口的实现类都是谁用谁写。
* 我们一般写的都是该接口的子接口实现类:MethodInterceptor
*/
public class Client {
public static void main(String[] args) {
final Producer producer = new Producer();
Producer cglibProducer = (Producer)Enhancer.create(
producer.getClass(),
new MethodInterceptor() {
/**
* 执行被代理对象的任何方法都会先执行此方法
* @param object
* @param method
* @param objects
* @param methodProxy 当前执行方法的代理对象
* @return
* @throws Throwable
*/
public Object intercept(Object object, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
// 提供增强的方法
Object res = null;
//1、获取方法执行的参数
Float money = (Float) objects[0];
//2、判断当前方法是不是销售
if ("saleProduct".equals(method.getName())) {
res = method.invoke(producer, money * 0.8f);
}
return res;
}
});
cglibProducer.saleProduct(12000f);
}
}