反射的三种应用场景
1.工厂模式中的简单工厂模式优化
2.代理模式中的动态代理方式实现
3.Java JDBC数据库操作
1.工厂模式使用(log工厂模式)
2.代理模式
代理(Proxy)模式是一种设计模式,通过代理对象来访问目标对象,还可以在不修改目标对象的情况下,对代理对象进行拓展,增强目标对象的功能
什么是静态代理?
1.静态代理属于代理模式的一种代理方式,需要代理对象和目标对象实现相同的接口
2.静态代理的代理类是由程序员编写源码,编译后即可获取到代理类的class字节码文件,也就是在程序运行前就已经得到实际的代理类class字节码文件了
什么是动态代理?
1.动态代理也属于代理模式的一种代理方式,不过只需要目标对象实现接口,代理对象不需要实现接口~
2.动态代理的代理类编译后是没有class字节码文件的,而是在运行时利用Java反射机制动态的生成代理类的class字节码文件
jdk原生代码示例
public interface IUserDao {
//添加数据
public void insert();
}
public class UserDao implements IUserDao{
@Override
public void insert() {
System.out.println("添加数据");
}
}
public class UserProxy {
private Object target; //目标对象
public UserProxy(Object target) {
this.target = target;
}
/**
* 利用JDK API获取到代理对象
* @return
*/
public Object getProxyInstance() {
//目标对象的加载器
ClassLoader loader = target.getClass().getClassLoader();
//目标对象的实现接口类型
Class<?>[] interfaces = target.getClass().getInterfaces();
//InnvocationHandler事件处理器实例对象
InvocationHandler h = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("添加数据前:手动开启事务");
// 执行目标对象方法
Object value = method.invoke(target, args);
System.out.println("添加数据后:手动提交事务");
return null;
}
};
//传入3个参数,创建代理类的实例对象,并返回
return Proxy.newProxyInstance(loader, interfaces,h);
}
}
public class UserProxyTest {
@Test
public void test() {
IUserDao target = new UserDao();
System.out.println("目标对象信息:" + target.getClass());
//获取代理类实例对象
IUserDao proxy = (IUserDao) new UserProxy(target).getProxyInstance();
System.out.println("代理对象信息:" + proxy.getClass());
//执行代理方法
proxy.insert();
}
}
运行结果
目标对象信息:class com.justin.java.reflect.UserDao
代理对象信息:class com.sun.proxy.$Proxy2
添加数据前:手动开启事务
添加数据
添加数据后:手动提交事务
cglib代码示例
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 EnhancerDemo {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(EnhancerDemo.class);
enhancer.setCallback(new MethodInterceptorImpl());
EnhancerDemo demo = (EnhancerDemo) enhancer.create();
demo.test();
System.out.println(demo);
}
public void test() {
System.out.println("EnhancerDemo test()");
}
private static class MethodInterceptorImpl implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.err.println("Before invoke " + method);
Object result = methodProxy.invokeSuper(o, objects);
System.err.println("After invoke" + method);
return result;
}
}
}
运行结果
EnhancerDemo test()
After invokepublic void com.bruis.learnaop.testcglibaop.EnhancerDemo.test()
Before invoke public java.lang.String java.lang.Object.toString()
Before invoke public native int java.lang.Object.hashCode()
After invokepublic native int java.lang.Object.hashCode()
After invokepublic java.lang.String java.lang.Object.toString()
com.bruis.learnaop.testcglibaop.EnhancerDemo$$EnhancerByCGLIB$$413eae0d@53e25b76
区别
JDK代理使用的是反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
CGLIB代理使用字节码处理框架asm,对代理对象类的class文件加载进来,通过修改字节码生成子类。
jdk动态代理只提供实现接口的目标类代理,不支持没有实现接口的目标类的代理。如果目标类没有实现接口,只能用cglib代理
JDK代理是不需要依赖第三方的库,只要JDK环境就可以进行代理,需要满足以下要求:
1.实现InvocationHandler接口,重写invoke()
2.使用Proxy.newProxyInstance()产生代理对象
3.被代理的对象必须要实现接口
CGLib 必须依赖于CGLib的类库,需要满足以下要求:
1.实现MethodInterceptor接口,重写intercept()
2.使用Enhancer对象.create()产生代理对象
spring中动态代理Aop片段
![在这里插入图片描述](https://img-blog.csdnimg.cn/c222f6a69cb44732856c4b439f38d79d.png
原文转载:https://blog.csdn.net/JustinQin/article/details/119850304
https://blog.csdn.net/CoderBruis/article/details/100042081