一、代理
public interface Calculator {
//加
int add(int a, int b);
//减
int sub(int a, int b);
//乘
int mul(int a, int b);
//除
int div(int a, int b);
}
1.1 静态代理
public class CalculatorImpl implements Calculator {
@Override
public int add(int a, int b) {
int res = a+b;
System.out.println("方法内部 result = " + res);
return res;
}
@Override
public int sub(int a, int b) {
int res = a-b;
System.out.println("方法内部 result = " + res);
return res;
}
@Override
public int mul(int a, int b) {
int res = a*b;
System.out.println("方法内部 result = " + res);
return res;
}
@Override
public int div(int a, int b) {
int res = a/b;
System.out.println("方法内部 result = " + res);
return res;
}
}
public class CalProxy implements Calculator {
//把被代理目标对象传递进来
private Calculator calculator;
public CalProxy(Calculator calculator) {
this.calculator = calculator;
}
@Override
public int add(int a, int b) {
System.out.println("[日志] add 方法开始了,参数是:"+a+","+b);
int result = calculator.add(a,b);
System.out.println("[日志] add 方法结束了,返回值是:"+result);
return result;
}
@Override
public int sub(int a, int b) {
System.out.println("[日志] sub 方法开始了,参数是:"+a+","+b);
int result = calculator.sub(a,b);
System.out.println("[日志] sub 方法结束了,返回值是:"+result);
return result;
}
@Override
public int mul(int a, int b) {
System.out.println("[日志] mul 方法开始了,参数是:"+a+","+b);
int result = calculator.mul(a,b);
System.out.println("[日志] mul 方法结束了,返回值是:"+result);
return result;
}
@Override
public int div(int a, int b) {
System.out.println("[日志] div 方法开始了,参数是:"+a+","+b);
int result = calculator.div(a,b);
System.out.println("[日志] div 方法结束了,返回值是:"+result);
return result;
}
}
1.2 动态代理
/*动态代理*/
public class ProxyFactory {
//目标对象
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
//返回代理对象
public Object getProxy(){
/*
* 三个参数
* 1.classLoader加载动态生成代理类的类加载器
* 2.interface目标对象实现的所有接口的class类型数组
* 3.handler设置代理对象实现目标对象方法的过程
* */
ClassLoader classLoader = target.getClass().getClassLoader();
Class<?>[] interfaces = target.getClass().getInterfaces();
InvocationHandler handler = new InvocationHandler(){
/*
* proxy:代理对象
* method:需要重写目标对象的方法
* args:方法的参数
* */
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//调用方法前日志的输出
System.out.println("[动态代理][日志]:" + method.getName() + ",参数:" + Arrays.toString(args));
//调用目标的方法
Object res = method.invoke(target, args);
//调用方法后日志的输出
System.out.println("[动态代理][日志]:" + method.getName() + ",结果:" + res);
return res;
}
};
return Proxy.newProxyInstance(classLoader, interfaces, handler);
}
}
测试
@Test
public void test(){
//1.创建动态代理对象
ProxyFactory proxyFactory = new ProxyFactory(new CalculatorImpl());
Calculator proxy = (Calculator) proxyFactory.getProxy();
proxy.add(3,5);
}

二、AOP
通过预编译方式和运行期动态代理方式实现,在不修改源代码的情况下,给程序动态统一添加额外功能的一种技术。
jdk动态代理和cglib动态代理:
有接口使用jdk代理,生成接口实现类代理对象--代理对象和目标对象实现同样的接口
没有接口使用cglib代理,生成子类代理对象---通过继承被代理的目标类
2.1 添加依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>6.0.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>6.0.2</version>
</dependency>
2.2 Calculate接口和实现类
public interface Calculator {
//加
int add(int a, int b);
//减
int sub(int a, int b);
//乘
int mul(int a, int b);
//除
int div(int a, int b);
}
public class CalculatorImpl implements Calculator {
@Override
public int add(int a, int b) {
int res = a+b;
System.out.println("方法内部 result = " + res);
return res;
}
@Override
public int sub(int a, int b) {
int res = a-b;
System.out.println("方法内部 result = " + res);
return res;
}
@Override
public int mul(int a, int b) {
int res = a*b;
System.out.println("方法内部 result = " + res);
return res;
}
@Override
public int div(int a, int b) {
int res = a/b;
System.out.println("方法内部 result = " + res);
return res;
}
}
2.3 创建切面类
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--开启组件扫描,要扫描的包名写的越具体越好,因为越具体扫描花费的时间越少-->
<context:component-scan base-package="com.hait"/>
<!--开启Aspectj自动代理,为目标对象生成代理-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
切面类
@Aspect //切面类
@Component //ioC容器
public class LogAspect {
//设置切入点和通知类型
//1.通知类型:
// 前置@Before(value="execution(权限修饰符 方法返回值 增强方法的全类名.方法名(参数类型))")
//* com.hait.dao.impl.CalculatorImpl.*(..)表示包中的所有类的所有方法任意参数类型
@Before(value = "execution(* com.hait.dao.impl.*.*(..))")
public void beforeMethod(JoinPoint joinPoint){
String method = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
System.out.println("Logger-->前置通知,方法名:"+method+"参数:"+ Arrays.toString(args));
}
// 返回@AfterReturning()
@AfterReturning(value = "execution(* com.hait.dao.impl.*.*(..))",returning = "res")
public void afterReturning(JoinPoint joinPoint,Object res){
String method = joinPoint.getSignature().getName();
System.out.println("Logger-->返回通知,方法名:"+method+",返回值:"+res);
}
// 异常@AfterThrowing()---目标方法出现异常时执行
@AfterThrowing(value = "execution(* com.hait.dao.impl.*.*(..))",throwing = "ex")
public void afterThrowing(JoinPoint joinPoint,Exception ex){
String method = joinPoint.getSignature().getName();
System.out.println("Logger-->异常通知,方法名:"+method+",异常:"+ex);
}
// 后置@After()
@After(value = "execution(* com.hait.dao.impl.*.*(..))")
public void afterMethod(JoinPoint joinPoint){
String method = joinPoint.getSignature().getName();
System.out.println("Logger-->后置通知,方法名:"+method);
}
// 环绕@Around()
@Around(value = "execution(* com.hait.dao.impl.*.*(..))")
public Object aroundMethod(ProceedingJoinPoint joinPoint){
String method = joinPoint.getSignature().getName();
String args = joinPoint.getArgs().toString();
System.out.println("Logger-->环绕通知,方法名:"+method);
Object res = null;
try {
System.out.println("Logger-->环绕通知----目标方法之前执行");
//调用目标方法
res = joinPoint.proceed();
System.out.println("Logger-->环绕通知----目标方法之后执行");
} catch (Throwable throwable) {
throwable.printStackTrace();
System.out.println("Logger-->环绕通知----目标方法出现异常执行");
}finally {
System.out.println("Logger-->环绕通知----目标方法执行完毕执行");
}
return res;
}
}

测试
@Test
public void test02() {
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
Calculator calculator = ac.getBean(Calculator.class);
calculator.div(3, 0);
}

没有异常的话

三、重用切入点表达式
//重用切入点表达式
@Pointcut(value = "execution(* com.hait.dao.impl.*.*(..))")
public void pointCut(){
}
// 后置@After()
/*如果pointCut方法不在本类中,那么value的值是方法的全路径
*@After(value = "com.hait.annoaop.LogAspect.pointCut()")
*/
@After(value = "pointCut()")
public void afterMethod(JoinPoint joinPoint){
String method = joinPoint.getSignature().getName();
System.out.println("Logger-->后置通知,方法名:"+method);
}
6563

被折叠的 条评论
为什么被折叠?



