代理
什么是代理
1、代理是一种设计模式,用于访问对象,引入间接层。可以通过代理对象间接对实际对象进行访问,代理对象可以在访问处理实际对象前后做一些额外的处理,比如打日志,事务等,
2、有什么作用?可以让实际对象只需要实现好自己的作用,额外的和实际对象无关的处理可以通过代理来实现。比如代购,生产厂商(实际对象)只需要负责生产商品,代购方(代理)帮助生产方做额外操作(比如,发货,售后等等),购买方也只需要关心能通过代理购买到自己想要的商品并且由代理提供发货售后等服务。
代理的几个要素
- 接口interface:代理对象和实际对象要实现相同的接口,代理对象才能代替实际对象去执行相同的操作。通过实现相同的接口,代理对象可以保证对外提供的方法和真实对象是一致的,从而实现透明的代理操作
- 真实对象:代理对象的实际执行者,代理对象通过他来实现具体的业务逻辑。
- 代理对象:真实对象的代表,他可以在调用真实对象的前后做一些额外的处理,比如:日志、事务等。
静态代理
静态代理是在编译时就已经确定代理类的代码,代理类和被代理类之间的关系在编译时就确定了,无法在运行时动态改变。
以下是一个代码demo,以实际生活中,餐厅和预制菜加工厂为例子,餐厅是代理对象,预制菜加工厂是真实对象。
接口interface
public interface DishesProduceInterface {
// 生产菜品
void produceDishes();
}
预制菜生产加工厂
public class KitchenProduce implements DishesProduceInterface {
@Override
public void produceDishes(){
System.out.println("生产预制菜");
}
}
餐厅
public class RestaurantProxy implements DishesProduceInterface{
KitchenProduce kitchenProduce;
public RestaurantProxy(KitchenProduce kitchenProduce) {
this.kitchenProduce = kitchenProduce;
}
@Override
public void produceDishes(){
System.out.println("接到订单");
kitchenProduce.produceDishes();
System.out.println("加热处理预制菜,送到顾客手上");
}
}
public class ProxyDemo {
public static void main(String[] args) {
KitchenProduce kitchenProduce = new KitchenProduce();
RestaurantProxy restaurantProxy = new RestaurantProxy(kitchenProduce);
restaurantProxy.produceDishes();
}
}
上面的例子中,预制菜生产加工厂为真实对象,负责生产预制菜菜品,餐厅为代理对象,负责接订单,真实对象(预制菜生产加工厂)生产菜品后,餐厅在进行加热处理后送到顾客手上。这样一个代理模式。
动态代理
动态代理是在运行时动态生成代理类的代码,并且可以在运行时动态地指定代理类的行为。它通过使用Java的反射机制,在运行时创建一个实现了一组接口的代理类,并将方法的调用转发到真实对象上。
-
InvocationHandler接口是Java动态代理机制中的一个关键接口。它定义了一个invoke方法,当代理对象的方法被调用时,invoke方法会被调用。在invoke方法中,可以实现对代理对象方法的增强、拦截、记录日志等操作。
-
Proxy类是Java动态代理机制的核心类。它提供了创建动态代理类和对象的静态方法。通过Proxy类的newProxyInstance方法,可以根据指定的接口和InvocationHandler对象创建一个代理对象。
以下是一个java 动态代理的demo
编写一个自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface MyTransactional {
}
编写一个interface接口
public interface BaseServiceInterface<T> {
List<T> select();
@MyTransactional
boolean save();
}
编写两个实现类
public class UserServiceImpl implements BaseServiceInterface<User>{
@Override
public List<User> select() {
System.out.println("User查询操作");
return null;
}
@Override
public boolean save() {
System.out.println("User保存操作");
return false;
}
}
public class RoleServiceImpl implements BaseServiceInterface<Role>{
@Override
public List<Role> select() {
System.out.println("Role查询操作");
return null;
}
@Override
public boolean save() {
System.out.println("Role保存操作");
return false;
}
}
实现InvocationHandler接口
public class MyTransactionalHandler implements InvocationHandler {
private Object target;
public MyTransactionalHandler(Object object) {
this.target = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
if(method.getAnnotation(MyTransactional.class) != null) {
System.out.println("开启事务");
result = method.invoke(target,args);
System.out.println("结束事务");
} else {
result = method.invoke(target,args);
}
return result;
}
}
public class Demo {
public static void main(String[] args) {
UserServiceImpl userService = new UserServiceImpl();
BaseServiceInterface userServiceInterface = (BaseServiceInterface)Proxy.newProxyInstance(
UserServiceImpl.class.getClassLoader(),
UserServiceImpl.class.getInterfaces(),
new MyTransactionalHandler(userService));
userServiceInterface.save();
System.out.println("-----------------------");
userServiceInterface.select();
System.out.println("-----------------------");
RoleServiceImpl roleService = new RoleServiceImpl();
BaseServiceInterface roleServiceInterface = (BaseServiceInterface)Proxy.newProxyInstance(
UserServiceImpl.class.getClassLoader(),
UserServiceImpl.class.getInterfaces(),
new MyTransactionalHandler(roleService));
roleServiceInterface.save();
System.out.println("-----------------------");
roleServiceInterface.select();
}
}
输出结果如下:
如上动态代理通过Proxy.newProxyInstance()在运行时动态地创建代理类和代理对象,并在代理对象的方法被调用时执行指定的逻辑。无需像静态代理一样每个真实类都去手动编写代理类,可以减少代码量,实现通用的代理逻辑,但缺点是相比静态代理,运行时性能略低。