如题,面试问代理在项目中那些地方用到了,实际开发代理怎么用的,有点蒙,我只知道静态代理和动态代理的区别,还有jdk和CGLIB的区别。 在网上查也基本都是说区别,很少帖子见到说实战怎么用代理的。
你看下事务的源码,就用到了代理,还有aop切面 等等
代理的含义是在不改变原始类的情况下,给原始类进行功能扩展或增强,所以底层绝对是继承,实际开发中,代理通常用于以下场景:
日志记录:在业务代码执行前后记录相关日志信息;
权限控制:对指定业务方法进行权限控制,只允许特定角色的用户访问;
缓存控制:根据业务需要,对一些方法进行缓存控制,提高系统性能;
事务控制:对于涉及到多个数据操作的业务方法,需要进行事务管理,保证数据操作的一致性;
异常处理:在业务代码抛出异常时,进行相关处理,如发邮件、短信通知等。
在 Spring 中,AOP 通过切面(Aspect)来实现。切面是一种横切关注点(Crosscutting Concern),它跨越一个系统中多个组件,提供一种与这些组件协作的方式。通过定义通用的切面(Aspect),我们可以在不改变原始类的情况下,对它进行功能增强。Spring 提供了多种切面实现方式,包括基于注解、XML 配置文件、自定义注解等。
可以定义一个切面来记录系统的日志信息:
@Aspect
@Component
public class LoggerAspect {
@Before("execution(* com.example.service.*.*(..))")
public void before(JoinPoint joinPoint) throws Throwable {
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
// 记录日志信息
System.out.println("调用 " + methodName + "() 方法,参数:" + Arrays.toString(args));
}
}
这个切面会在 com.example.service 包下的所有方法执行前打印出方法名和参数信息,实现日志记录的功能。在使用时,我们需要在 Spring 的配置文件中声明这个切面:
<aop:aspectj-autoproxy />
然后在需要记录日志的 Service 上使用 @Service 注解,这样这个 Service 的所有方法都会被切面代理,实现了日志记录的功能。代理在实际开发项目中的应用: 1. AOP实现:通过代理实现横切关注点的分离,从而模块化开发。例如,可以使用代理在方法前后加上日志、事务等功能。 2. 延迟加载:通过代理实现延迟加载对象,可以提高系统性能。 3. 访问控制:通过代理对访问进行控制,可以保证系统的安全性。 4. 实现远程调用:通过代理实现远程调用,可以将服务提供者和服务消费者解耦,方便实现分布式系统。 5. 实现装饰器模式:通过代理实现装饰器模式,可以动态地给对象增加行为,而无需更改原始对象的代码。
在具体使用代理时,可以按照以下步骤: 1. 根据需要选择静态代理还是动态代理,以及使用JDK代理还是CGLIB代理。 2. 编写需要代理的接口和实现类。 3. 编写代理类,在代理类中注入需要代理的实现类,并在代理类中增加需要的功能实现。 4. 在代码中使用代理类,而不是直接使用实现类。
例如,使用动态代理实现AOP功能: 1. 定义一个需要代理的接口:
public interface UserService {
void addUser(User user);
void deleteUser(int userId);
}
public class UserServiceImpl implements UserService {
public void addUser(User user) {
// 添加用户的业务逻辑
}
public void deleteUser(int userId) {
// 删除用户的业务逻辑
}
}
public class LogServiceProxy implements InvocationHandler {
private Object target; // 需要代理的目标对象
public LogServiceProxy(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before method: " + method.getName());
Object ret = method.invoke(target, args);
System.out.println("After method: " + method.getName());
return ret;
}
// 创建代理对象
public static Object createProxy(Object target) {
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), new LogServiceProxy(target));
}
}
UserServiceImpl userService = new UserServiceImpl();
UserService proxyInstance = (UserService) LogServiceProxy.createProxy(userService);
proxyInstance.addUser(new User());
proxyInstance.deleteUser(1);
以上是一个简单的实现。在实际项目中,可以根据不同需求选择不同的代理方式和实现方式。