基于动力节点视频做的笔记:
首先了解什么是代理
代理可以理解为中介:用户不能直接通过厂家购买少量的商品,只能通过淘宝等中间商购买,但是淘宝商家不是直接供货的,只是间接的供货—购买的事件最终是调用的目标方法是厂家提供的。
作用:1.目标方法的调用,2.方法的增强
静态代理
代理的目标明确,容易理解,但是目标方法多,编写繁琐,容易出错。
如果需要提供新的工厂接口方法,自己明确知道代理类中的方法。。
public interface SayHello {
void say(String name);
void print();
}
public class SayHelloImpl implements SayHello {
@Override
public void say(String name) {
out.println(name);
}
@Override
public void print() {
}
}
package com.interview.proxytest;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author helloLi
* @version 1.0
* @date 2020/6/13 17:40
*
* 测试jdk中的反射机制(mothod代表目标方法)
* 使用mothod方法(代表目标方法)进行调用invoke方法进行调用任意对象的的目标方法
*/
public class TestAop {
public static void main(String[] args) throws Exception {
// 通过反射机制执行sayhello方法 ,核心是mothod方法
SayHello target = new SayHelloImpl();
// 获取sayhello名称对于mothod的类的对象
Method method = SayHello.class.getMethod("say", String.class);
Method mothod2 = SayHello.class.getMethod("print",int.class);
// 通过mothod可以执行sayhello方法调用
//invoke是moethod类中的一个方法,表示执行调用 Oject表示对象的方法 Object...args 表示执行时候的参数
SayHello target2 = new SayHelloImpl();
Object lisi = method.invoke(target, "lisi");
Object lisi2 = method.invoke(target2, "wangwu");
mothod2.invoke(target, 1);
// Proxy proxy = new Proxy();
}
}
jdk动态代理(基于接口与反射)
代理的类是不明确的,需要传递参数确定代理类的信息,目标方法
实现invocationHandler接口
怎么用:
1.创建类实现接口invocationHandler;;
重写invoke()方法,,把原来的静态代理类完成的功能写在这
-
mothod类:表示方法的,确切的说是目标类中的方法,作用:通过mothod可以执行某个目标类的方法:不需要知道执行的方法名
Object lisi = method.invoke(target, “lisi”);
Object lisi2 = method.invoke(target2, “wangwu”);
等同于静态代理中的代理类调用目标类中的方法调用 -
Proxy类:是核心,创建代理对象,之前是new 构造方法
现在使用proxy中的方法来代替
方法:静态方法:newProxyInstance();
1.参数:classLaoder loader;类加载器,负责向内存中加载对象,使用反射获取对象的classLaoder类,a.getClass .getclassLoader() 目标对象的类加载器
2.class<?>接口,目标对象实现的接口,也是反射获取 -
invocationHandler h自己写的代理代理类需完成的功能
// 目标接口
public interface UsbSell {
float sell(int amount);
float buy(int amount);
void print();
}
package com.interview.proxytest.auto;
/**
* @author helloLi
* @version 1.0
* @date 2020/6/13 20:47
*/
// 目标类
public class UsbKingFactory implements UsbSell {
@Override
public float sell(int amount) {
System.out.println("目标类中的目标方法");
return 23;
}
@Override
public float buy(int amount) {
System.out.println("目标方法新增的购买方法");
return 10;
}
@Override
public void print() {
//不影响代理类
}
}
package com.interview.proxytest.auto;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* @author helloLi
* @version 1.0
* @date 2020/6/13 20:48
*/
// 必须实现invocationHandler接口,完成代理类的功能(调用目标方法,功能增强)
public class MySellHandler implements InvocationHandler {
private Object target = null;
public MySellHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 参考静态的代理类的
Object res = null;
// 动态的说明不固定,需要传入目标对象
res = method.invoke(target,args);//执行目标方法
//功能增强
if(res != null){
Float price = (Float)res;
price = price + 25;
res = price;
}
System.out.println("动态代理增强");
return res;
}
}
package com.interview.proxytest.auto;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
/**
* @author helloLi
* @version 1.0
* @date 2020/6/13 20:56
*/
public class MainShop {
public static void main(String[] args) {
// 创建目标对象
UsbSell factory = new UsbKingFactory();
// 创建invocationHandler对象
InvocationHandler invocationHandler = new MySellHandler(factory);
// 创建代理对象 不像静态的代理类的对象 事先知道目标调用方法名与参数
UsbSell proxyInstance = (UsbSell) Proxy.newProxyInstance(factory.getClass().getClassLoader(),
factory.getClass().getInterfaces(), invocationHandler);
// 通过动态代理执行目标方法--------底层实现的是invokeHandler对象中的invoker方法。
float price = proxyInstance.buy(1);
float buy = proxyInstance.sell(1);
System.out.println("通过动态代理对象,调用:"+ price+" / "+ buy);
}
}
Cglib可以实现不是基于接口的目标方法方法的代理
既可以基于接口也可以基于一般类
cglib代理类核心是子类增强父类,将目标方法所在类作为父类,在子类中增强。
回调方法是指达到一定的条件就会触发的方法
说是调用目标方法回触发回调没有理解
package com.interview.cglib.cglib2;
/**
* @author helloLi
* @version 1.0
* @date 2020/6/14 11:56
*
* 基于cglib的代理,需要自己手工创建工厂
*/
// 目标类的方法,是没有实现接口
public class SellService {
public String sell(){
System.out.println("卖东西方法");
return "helloWorld";
}
public String buy(){
System.out.println("买东西方法");
return "32块";
}
}
package com.interview.cglib.cglib2;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.omg.CORBA.PUBLIC_MEMBER;
import java.lang.reflect.Method;
/**
* @author helloLi
* @version 1.0
* @date 2020/6/14 12:00
*/
public class CglibFactory implements MethodInterceptor {
private SellService target;
public SellService myCglibSell(){
// 增强
Enhancer enhancer = new Enhancer();
// 目标类设置为父类,基于cglib增强的特点:子类增强父类---指定目标类为父类
enhancer.setSuperclass(SellService.class);
//怎么增强--回头再调用,达到执行条件之后回头在调用,this表示当前的对象
enhancer.setCallback(this);
// create() 用于创建 cglib动态代理的对象
return (SellService) enhancer.create();
}
public CglibFactory() {
}
public CglibFactory(SellService target) {
this.target = target;
}
// 回调接口的方法:触发执行的条件--执行目标方法时候回触发该方法
// 增强的原理是子类增强父类
@Override
public Object intercept(Object o, Method method,
Object[] objects, MethodProxy methodProxy) throws Throwable {
Object invoke = method.invoke(target, objects);
if (invoke != null){
invoke = ((String)invoke).toUpperCase();
}
System.out.println("增强");
invoke = invoke+"得了";
return invoke;
}
}
package com.interview.cglib.cglib2;
import com.interview.JSONUtil;
import org.w3c.dom.ls.LSOutput;
/**
* @author helloLi
* @version 1.0
* @date 2020/6/14 12:51
*/
public class MyTest {
public static void main(String[] args) {
SellService target = new SellService();
SellService sevice = new CglibFactory(target).myCglibSell();
String result = sevice.buy();
System.out.println(result);
String sell = sevice.sell();
System.out.println(sell);
}
}