静态代理
与动态代理的区别:在代码编译时就确定了所需要代理的类,静态代理的代理类只针对一个被代理类,动态代理在代码编译时
期还不能确定所需要代理的类,只能根据类的动态加载机制,在代码运行时加载被代理得类,动态代理可以针对多个被代理类(委托类)
示例
(由于Java api 机制 代理类和委托类必须要实现他们共同的接口)
package top;
import top.TopInterface;
/**
* @author: yongtong
* @Date: 2021/11/18 22:22:42
* @Description: 静态代理:在知道具体被代理类的情况下可以使用静态代理
* 静态代理只对应一个委托类,一下代码是一个委托类
*/
public class StaticAgency implements TopInterface {
public void palyGame(String gameName, String desc) {
System.out.println("告知委托人"+gameName+"...."+desc);
}
public void eat(String foodName, String des) {
System.out.println("告知委托人"+foodName+"....."+des);
}
}
package top;
import lombok.Data;
/**
* @author: yongtong
* @Date: 2021/11/18 23:23:06
* @Description: 代理类
*/
@Data
public class Agency implements TopInterface{
private StaticAgency staticAgency;
public void palyGame(String gameName, String desc) {
System.out.println("代理告知");
staticAgency.palyGame(gameName, desc);
System.out.println("代理告知结束");
}
public void eat(String foodName, String des) {
System.out.println("代理告知");
staticAgency.eat(foodName, des);
System.out.println("代理告知结束");
}
}
import org.junit.Test;
import top.Agency;
import top.StaticAgency;
/**
* @author: yongtong
* @Date: 2021/11/18 23:23:16
* @Description: 测试
*/
public class TestDemo {
@Test
public void text(){
Agency agency = new Agency();
agency.setStaticAgency(new StaticAgency());
agency.palyGame("开始游戏时间","真好玩");
agency.eat("吃个桃桃","好凉凉");
}
}
package top;
/**
* @author: yongtong
* @Date: 2021/11/18 23:23:00
* @Description: 顶层接口代理类和委托类都必须要实现此接口
*/
public interface TopInterface {
void palyGame(String gameName, String desc);
void eat(String foodName,String des);
}
总结:
从以上代码可以看出代理类拥有委托类的所有属性和方法,而方法真正的执行者是委托类,代理类可以在委托类方法执行方法之前和之后添加功能
JDK 代理
jdk代理属于接口代理,是由jdk提供的代理,jdk产生代理需要被代理类和代理类实现同一个接口,根据双方的共同的接口去产生
的代理对象,产生的代理对象为接口的实现类
package dynamicproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* @author: yongtong
* @Date: 2021/11/19 19:19:59
* @Description: jdk代理类(产生代理对象)
*/
public class JDKProxy implements InvocationHandler {
//目标类
private Object obj;
public JDKProxy(Object obj) {
this.obj = obj;
}
public JDKProxy(){
super();
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("真实对象执行方法之前");
//调用真实对象的方法
Object invoke = method.invoke(obj, args);
System.out.println("真实对象执行方法之后");
return invoke;
}
}
import dynamicproxy.JDKProxy;
import org.junit.Test;
import top.StaticAgency;
import top.TopInterface;
import java.lang.reflect.Proxy;
/**
* @author: yongtong
* @Date: 2021/11/19 20:20:08
* @Description: 测试
*/
public class ProxyJdkText {
@Test
public void text(){
TopInterface topService = new StaticAgency();
//代理工厂产生代理实例
JDKProxy jdkProxy = new JDKProxy(topService);
//将代理的实例赋值给接口的引用(根据jdk自带的代理类方法)
TopInterface top = (TopInterface) Proxy.newProxyInstance(
topService.getClass().getClassLoader(),
topService.getClass().getInterfaces(),
jdkProxy);
top.palyGame("小猪佩奇","很二");
top.eat("猪shit","很香");
}
}
cglib 代理
cglib 代理为子类代理,代理类和被代理类不需要实现同一个接口,产生的代理类为被代理类的子类也就是说此代理类继承了
被代理类,属于第三方框架 ,依靠ASM 字节码框架才能产生
package dynamicproxy;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* @author: yongtong
* @Date: 2021/11/19 21:21:03
* @Description: cglib代理
*/
public class CglibProxy implements MethodInterceptor {
//目标对象
private Object obj;
public CglibProxy(Object obj) {
this.obj = obj;
}
public CglibProxy(){}
/**
* 返回代理对象
*
*/
public Object createProxy() {
Enhancer enhancer = new Enhancer();
//回调函数
enhancer.setCallback(this);
//设置代理对象的父类
enhancer.setSuperclass(this.obj.getClass());
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("真实对象执行方法之前");
//调用真实对象的方法
Object invoke = method.invoke(obj, objects);
System.out.println("真实对象执行方法之后");
return invoke;
}
}
import dynamicproxy.CglibProxy;
import entity.RealClass;
import org.junit.Test;
/**
* @author: yongtong
* @Date: 2021/11/19 21:21:11
* @Description: 测试
*/
public class CglibText {
@Test
public void Test(){
RealClass topService = new RealClass();
CglibProxy cglibProxy = new CglibProxy(topService);
RealClass proxy = (RealClass) cglibProxy.createProxy();
proxy.realMethod();
}
}
package entity;
/**
* @author: yongtong
* @Date: 2021/11/19 21:21:35
* @Description: cglib 测试真实类(目标类)
*/
public class RealClass {
public void realMethod(){
System.out.println("真实类方法");
}
}
枚举(enum)
java 1.5 之后推出的一种专门存储整型常量的集合,可以以面向对象的思维去控制这些整型常量
魔法值:
一些带有歧义的变量值,比如 0 和1
我们可以把这个两个数字看作一种状态或者就是他们本身所代表的数字
为了改善我们可以将这种有歧义的变量放入枚举中用一个具体的值来代替它
package myenum;
/**
* @author: yongtong
* @Date: 2021/11/19 22:22:17
* @Description: 枚举
*/
enum State {
/**
* SHADOW : 关闭
* OPEN :开启
*
*/
SHADOW (0,"关闭"),OPEN(1,"开启");
private int i;
private String desc;
private State(int i, String desc) {
this.i = i;
this.desc = desc;
}
}
特点
- 枚举的定义和实例是放在一起的
- 枚举可以提供构造器,但构造器必须私有
- 枚举的实例必须放在第一行
使用
State.SHADOW.value