原理:使用Proxy类的newProxyInstance方法运行期通过反射动态的生成代理对象
优点:不需要修改具体的业务代码,动态的增强方法,降低耦合性。
缺点:代理的对象必须有接口实现。
代码如下:
接口:
package com.yellow.proxy.jdk;
public interface Iwork {
public abstract void service();
}
实现类:
package com.yellow.proxy.jdk;
public class IworkImpl implements Iwork {
public void service() {
System.out.println("提供服务");
}
}
切面类:
package com.yellow.proxy.jdk;
public class Advices {
public void log(){
System.out.println("记录日志");
}
public void transaction(){
System.out.println("事务操作");
}
}
测试类:
package com.yellow.proxy.jdk;
import org.junit.Test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyTest {
/**
* 使用jdk的动态代理来增强接口实现类
*/
@Test
public void test1(){
//创建目标对象
Iwork iwork = new IworkImpl();
//创建切面类
Advices advices = new Advices();
//创建代理对象
Iwork iwork_proxy = (Iwork)Proxy.newProxyInstance(iwork.getClass().getClassLoader(), iwork.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
advices.log();
Object invoke = method.invoke(iwork, args);
advices.transaction();
return invoke;
}
});
//使用代理对象调用方法
iwork_proxy.service();
}
}
测试结果:
原理:以创建目标类的子类来生成动态代理对象。
优点:不需要修改具体的业务代码,动态的增强方法,降低耦合性。
缺点:不能对final修饰的类,final修饰的方法或static的方法进行代理
代码如下:
目标类:
package com.yellow.proxy.cglib;
public class Work{
public void service() {
System.out.println("提供服务");
}
}
切面类:
package com.yellow.proxy.cglib;
public class Advices {
public void log(){
System.out.println("记录日志");
}
public void transaction(){
System.out.println("事务操作");
}
}
测试类:
package com.yellow.proxy.cglib;
import org.junit.Test;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibTest {
/**
* 使用cglib的动态代理来增强目标类 将被代理的类(不能为final)作为父类,创建子类去增强
*/
@Test
public void test1(){
//创建目标对象
Work work = new Work();
//增强的对象
Advices advices = new Advices();
//创建增强器
Enhancer enhancer = new Enhancer();
//设置目标类为父类
enhancer.setSuperclass(Work.class);
//设置回调(增强的具体体现)
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
advices.log();
Object invoke = method.invoke(work, objects);
advices.transaction();
return invoke;
}
});
//创建代理对象
Work proxy_work = (Work) enhancer.create();
proxy_work.service();
}
}
测试结果:
原理:在编译期织入代码,编译成class文件
优点:可以增强任何类,任何方法,包括(final,static修饰)
缺点:需要使用aspecj提供的Ajc编译器来编译Aj文件。
注意:测试的时候需要配置Aspect的环境
安装AspectJ 可以去官网下载 https://www.eclipse.org/aspectj/downloads.php
下载完了就有一个可执行的jar包,就可以next安装
idea设置:
还要将idea编译方式修改为Aj,maven的pom文件配置坐标
org.aspectj
aspectjweaver
1.8.13
org.aspectj
aspectjrt
1.8.13
代码如下:
注意:测试环绕增强的时候,要和其他增强分开测试,否则会报异常
Error:(22, 0) ajc: circular advice precedence: can't determine precedence between two or more pieces of advice that apply to the same join point: method-call(void com.yellow.aspectj.Work.test())
AspectJ文件,可以理解为一个类:
package com.yellow.aspectj;
public aspect FristAspectj {
//切入点
pointcut mypointcut():call(* Work.test(..));
//前置增强
before(): mypointcut(){
System.out.println("前置增强");
}
//最终增强
after():mypointcut(){
System.out.println("后置增强");
}
//异常增强
after() throwing(Exception e): mypointcut(){
System.out.println("异常增强了");
e.printStackTrace();
}
// //环绕增强
// Object around():mypointcut(){
// System.out.println("环绕前");
// Object proceed = proceed();
// System.out.println("环绕后");
// return proceed;
// }
}
测试类:
注意:需要测试final 和static 修饰的方法的时候,最好使用maven clean一下项目,否侧会影响测试结果
package com.yellow.aspectj;
import java.io.IOException;
public class Work {
public void test(){
System.out.println("提供服务");
}
public static void main(String[] args) throws IOException {
Work work = new Work();
work.test();
}
}
运行结果:
final修饰:
static修饰: