spring中aop
jdk动态代理
Proxy.newProxyInstance(类加载器,所有的接口,代理方法InvocationHandler )
public static void main(String[] args) {
CalculatorImpl calculator = new CalculatorImpl();
// 生成一个代理对象
/**
* 1.类加载器
* 2. 要生成的代理对象他需要实现的接口
* 3. InvocationHandle : 动态代理的方法
*
* 方法返回: 代理对象 这个对象需要实现的接、
*/
Calculator proxObj = (Calculator) Proxy.newProxyInstance(Main.class.getClassLoader(), new Class[]{Calculator.class}, new InvocationHandler() {
/**
*
* @param proxy 生成的代理对象
*
* @param method 被代理的方法
*
* @param args 方法的参数
*
* @return 代理方法的返回值
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long startTime = System.currentTimeMillis();
Object invoke = method.invoke(calculator, args);
long endTime = System.currentTimeMillis();
System.out.println(method.getName() + "方法执行时间" + (endTime - startTime));
return invoke;
}
});
proxObj.add(1, 2);
}
jdk动态代理,必须要有接口
cglib动态代理
cglib本质是写一个拦截器,把当前对象的方法拦截下来,进行增强,,返回一个当前对象的子类
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
实现MethodInterceptor
接口,创建一个拦截器:
package com.cj;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* @author cc
* @date 2025-02-20 09:25
**/
public class MyMethodInterceptor implements MethodInterceptor {
/**
* 方法的拦截器,,,,将目标方法拦截下来,, 拦截下来增强功能
* @param obj 代理的对象
* @param method 代理的方法
* @param args 代理的方法参数
* @param methodProxy 被代理的方法
* @return 代理方法的返回值
* @throws Throwable
*/
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
long startTime = System.currentTimeMillis();
// 生成一个继承他的类 ,,, 调用父类的方法
Object result = methodProxy.invokeSuper(obj, args);
long endTime = System.currentTimeMillis();
System.out.println("diff:"+(endTime-startTime));
return result;
}
}
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
// 设置父类 ==》 根据父类生成子类
enhancer.setSuperclass(UserService.class);
// 设置拦截器
enhancer.setCallback(new MyMethodInterceptor());
// 创建代理对象
UserService o = (UserService) enhancer.create();
o.sayHello();
}
生成了一个代理对象的子类,,
jdk动态代理只能代理有接口的类,,,cglib都能代理,,
spring中动态代理
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>6.1.14</version>
</dependency>
ProxyFactory
public static void main(String[] args) {
// spring中的动态代理使用的对象
ProxyFactory proxyFactory = new ProxyFactory();
// 设置被代理的对象
proxyFactory.setTarget(new CalculatorImpl());
proxyFactory.setInterfaces(Calculator.class);
// 设置为true,,,表示使用cglib动态代理 // 为false就会根据情况(是否有接口)自动选择
proxyFactory.setProxyTargetClass(true);
// 被代理方法上额外的增强逻辑
proxyFactory.addAdvice(new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Method method = invocation.getMethod();
long startTime = System.currentTimeMillis();
// 执行方法
Object proceed = invocation.proceed();
long endTime = System.currentTimeMillis();
System.out.println("diff:"+(endTime-startTime));
return proceed;
}
});
CalculatorImpl proxy = (CalculatorImpl) proxyFactory.getProxy();
proxy.add(1, 2);
}
spring中aop
通知:
- 前置通知 : 方法执行前调用
- 后置通知
- 返回通知 : 获取到方法返回值的时候调用
- 异常通知: 抛出错误的时候调用
- 环绕通知: 集大成者
写一个切面:
package com.cj;
import org.aopalliance.intercept.Joinpoint;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
/**
* 1.前置通知 :
* 后置通知
* 返回通知 : 拿到返回值的之后会触发,,, void也算是返回值
* 异常通知: 抛出异常的时候触发
* 环绕通知: 集大成者
*
* @author cc
* @date 2025-02-20 10:38
**/
public class LogAdvice {
public void before(JoinPoint jp){
// 目标方法的名字
String name = jp.getSignature().getName();
System.out.println(name+"方法开始执行了");
}
public void after(JoinPoint jp){
// 目标方法的名字
String name = jp.getSignature().getName();
System.out.println(name+"方法执行结束了");
}
/**
*
* @param jp
* @param val 目标方法的返回值 : 和目标方法的返回值类型一致
*/
public void afterReturning(JoinPoint jp,Void val){
// 目标方法的名字
String name = jp.getSignature().getName();
System.out.println(name+"方法afterReturning "+val);
}
public void afterThrowing(JoinPoint jp,Throwable e){
String name = jp.getSignature().getName();
System.out.println(name+"after throwing"+e.getMessage());
}
public Object around(ProceedingJoinPoint pjp){
String name = pjp.getSignature().getName();
Object proceed = null;
try {
System.out.println(name+"method start");
proceed = pjp.proceed();
System.out.println(name+"method end");
} catch (Throwable e) {
// 异常通知
System.out.println("exception");
throw new RuntimeException(e);
}
return proceed;
}
}
xml配置:
<bean class="com.cj.CalculatorImpl" id="calculatorImpl"/>
<bean class="com.cj.LogAdvice" id="logAdvice" />
<!-- 配置aop-->
<aop:config>
<aop:pointcut id="pc1" expression="execution(* com.cj.CalculatorImpl.*(..))"/>
<!-- 配置切面: 把切面的bean写进去-->
<aop:aspect ref="logAdvice">
<aop:before method="before" pointcut-ref="pc1" />
<aop:after method="after" pointcut-ref="pc1" />
<!-- 返回的值,,, 参数一个是jp,一个是val-->
<aop:after-returning method="afterReturning" pointcut-ref="pc1" returning="val"/>
<aop:after-throwing method="afterThrowing" pointcut-ref="pc1" throwing="e"/>
<aop:around method="around" pointcut-ref="pc1"/>
</aop:aspect>
</aop:config>
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
Calculator bean = ctx.getBean(Calculator.class);
System.out.println("bean = " + bean);
bean.add(1,2);
bean.sub(2,1);
}
<bean class="com.cj.CalculatorImpl" id="calculatorImpl"/>
这个实现类已经被代理了,已经取不到这个实现类的实例了,,
只能按照接口去找实现类,,,
<aop:config proxy-target-class="true">
: proxy-target-class为true表示使用cglib
java配置类使用aop
@Component
@Aspect // 标记这个类是一个切面
@EnableAspectJAutoProxy // 开启自动代理
public class LogAdvisor {
@Pointcut("execution(* com.cj.CalculatorImpl.*(..))")
public void pc1(){}
@Before("pc1()")
public void before(JoinPoint jp){
// 目标方法的名字
String name = jp.getSignature().getName();
System.out.println(name+"方法开始执行了");
}
@After("pc1()")
public void after(JoinPoint jp){
// 目标方法的名字
String name = jp.getSignature().getName();
System.out.println(name+"方法执行结束了");
}
/**
*
* @param jp
* @param val 目标方法的返回值 : 和目标方法的返回值类型一致
*/
@AfterReturning(value = "pc1()",returning = "val")
public void afterReturning(JoinPoint jp,Void val){
// 目标方法的名字
String name = jp.getSignature().getName();
System.out.println(name+"方法afterReturning "+val);
}
@AfterThrowing(value = "pc1()",throwing = "e")
public void afterThrowing(JoinPoint jp,Throwable e){
String name = jp.getSignature().getName();
System.out.println(name+"after throwing"+e.getMessage());
}
@Around("pc1()")
public Object around(ProceedingJoinPoint pjp){
String name = pjp.getSignature().getName();
Object proceed = null;
try {
System.out.println(name+"method start");
proceed = pjp.proceed();
System.out.println(name+"method end");
} catch (Throwable e) {
// 异常通知
System.out.println("exception");
throw new RuntimeException(e);
}
return proceed;
}
}
@EnableAspectJAutoProxy(proxyTargetClass = true)
// 开启自动代理 proxyTargetClass=true 表示使用cglib动态代理