动态代理模式
文章目录
一、动态代理
概念:程序运行的时候,根据要被代理的对象动态生成代理类(代理类不需要程序员自己去编写,由系统提供,
只需要关注业务方法的功能增强(处理))。
动态代理的分类:jdk动态代理和cglib动态代理。
1. jdk动态代理
jdk动态代理要求目标对象必须要实现接口。
其中有一个方法很重要
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h){
}
该方法可以为任何实现了该接口的对象提供代理对象,而且可以针对目标对象实现接口中的方法进行增强。
其中public interface InvocationHandler {
public Object invoke(Object proxy,Method method Object[] args)
throws Throwable;
}
method:指代目标对象接口中的方法,使用的时候,往往method.invoke(目标对象,参数)该方法中的invoke方法很重要。
public Object invoke(Object obj, Object… args)
obj====》调用当前对象的方法。
args===》参数
2.cglib动态代理
cglib动态代理:cglib代理生成目的对象的子类对象(底层在内存中生成了该目标对象的子类对象),会对目标对象中的所有方法都进行增强(处理),
cglib代理称为子类代理。
注意:要想使用cglib的话需要导入第三方jar包。
1 特点:目标对象不需要实现接口,就可以提供其代理对象
注意:对特殊方法(final),无法处理。
2 hibernate和spring底层广泛的使用到了cglib代理,但是面试的时候,一般问jdk为主。
3 核心方法功能:
Enhancer:核心类,提供目标对象的子类对象(代理对象)===》相当于Proxy
create():提供代理对象 ====》相当于newProxyInstance
MethodInterceptor:接口
intercept:抽象方法,对目标对象方法的增强
二、jdk代理模式代码
1.aop切面实体类
代码如下(示例):
public class TranAop {
public void before(){
System.out.println("开启事务");
}
public void after(){
System.out.println("提交事务");
}
public void exception(){
System.out.println("回滚事务");
}
public void myFinally(){
System.out.println("最终的操作");
}
}
2.接口
代码如下(示例):
//创建三个方法一个是修改,添加,查询。
public interface UserService {
void updateUser();
void insertUser(String name);
String findUserById(int id);
}
3.目标对象
public class UserServiceIpml implements UserService{
@Override
public void updateUser() {
System.out.println("修改操作");
}
@Override
public void insertUser(String name) {
System.out.println("插入操作:"+name);
}
@Override
public String findUserById(int id) {
System.out.println("查询操作");
return "user:"+id;
}
动态代理模式
public class jdkProxyFactory {
//先引入两个实体对象
private TranAop tranAop;
private UserService userService;
//注入目标对象
public jdkProxyFactory(TranAop tranAop, UserService userService) {
this.tranAop = tranAop;
this.userService = userService;
}
//工厂方法:提供代理对象
public Object getProxyFactory(){
return Proxy.newProxyInstance(userService.getClass().getClassLoader(),
//目标对象实现的接口
userService.getClass().getInterfaces(),
//回调函数只需要调用其中的invoke方法就可以其他不需要
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object obj=null;
if(method.getName().startsWith("find")){
obj=method.invoke(userService,args);
return obj;
}
try{
tranAop.before();
Object result= method.invoke(userService,args);//相当于此处调用目标对象 args:它会自动选择对象方法的参数
tranAop.after();
return result;
}catch (Exception e){
tranAop.exception();
throw e;
}finally {
tranAop.myFinally();
}
}
}
);
}
}
测试类
public class AppTest {
@Test
public void test1(){
TranAop tranAop = new TranAop();
UserServiceIpml userServiceIpml = new UserServiceIpml();
UserService userService = (UserService) new jdkProxyFactory(tranAop,userServiceIpml).getProxyFactory();
userService.insertUser("周止若");
userService.updateUser();
userService.findUserById(100);
}
}
三、cglib代理对象代码
目标对象
public class EmpService {
public void updateEmp(String name){
System.out.println("修改操作");
}
public void deleteEmp(int id){
System.out.println("删除操作");
}
cglib代理对象
public class cglibProxyFactory {
private TranAop tranAop;
private EmpService empService;
public cglibProxyFactory(TranAop tranAop, EmpService empService) {
this.tranAop = tranAop;
this.empService = empService;
}
public Object getCglibProxyFactory(){
return Enhancer.create(empService.getClass(),
new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
try {
tranAop.before();
Object result = methodProxy.invokeSuper(o,objects);
tranAop.after();
return result;
}catch(Exception e){
tranAop.exception();
throw e;
}finally{
tranAop.myFinally();
}
}
}
);
}
}
测试类
public class AppTest
{
@Test
public void test04(){
TranAop aop = new TranAop();
EmpService empService = new EmpService();
EmpService empService2 = (EmpService) new cglibProxyFactory(aop,empService).getCglibProxyFactory();
empService2.updateEmp("刘诗诗");
empService2.deleteEmp(3);
}
}
总结
jdk动态代理模式相对于cglib动态代理模式在运用上两者也不想上下,不过用jdk代理模式的还是相对于多一些。
静态代理模式和动态代理模式相比较来说的话动态代理模式应用更广泛,更灵活。