静态代理
静态代理的特点
代理对象
和被代理对象
实现同一个接口
代理对象
持有被代理对象
的引用
- 调用时,
代理对象
调用被代理对象
的相应方法,可以在调用的前后,增加额外功能
静态代理的实例
实例作用:保存数据时,进行事务控制
原方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Service public class UserService {
@Resource private UsUserMapper usUserMapper;
public void insertUser(){ UsUser usUser = new UsUser(); usUser.setUserId(1234567912); usUser.setUserAccount("测试用户"); usUserMapper.insert(usUser); } }
|
静态代理后
1.增加接口
1 2 3
| public interface UserServiceI { void insertUser(); }
|
2.被代理对象
实现接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @Service public class UserService implements UserServiceI{
@Resource private UsUserMapper usUserMapper;
@Override public void insertUser(){ UsUser usUser = new UsUser(); usUser.setUserId(1234567912); usUser.setUserAccount("测试用户"); usUserMapper.insert(usUser); } }
|
3.代理对象
实现接口,同时持有被代理对象
的引用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @Service public class UserStaticProxyService implements UserServiceI{
@Resource private UserService userService; @Resource PlatformTransactionManager platformTransactionManager; @Resource TransactionDefinition transactionDefinition;
@Override public void insertUser() { TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition); try { userService.insertUser(); platformTransactionManager.commit(transactionStatus); }finally { platformTransactionManager.rollback(transactionStatus); } } }
|
4.使用方式:注入代理类
的bean,由代理类
持有被代理类
的引用来调用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @RestController public class TestController {
@Resource private UserStaticProxyService userStaticProxyService;
@ApiOperation(value = "第一次测试接口",notes = "@author jungle") @GetMapping("/test/one") public ResponseEntity<String> testOne(){ userStaticProxyService.insertUser(); return ResponseEntity.ok().build(); } }
|
动态代理
静态代理和动态代理的区别
静态代理
在编译生成class文件,动态代理
在运行时生成字节码加载到JVM
静态代理
的代理对象
和被代理对象
都需要实现同一接口,动态代理则无此限制
JDK动态代理
实现方式
需要代理的类
需要实现一个接口中的所有抽象方法
- 通过
Proxy
类的newProxyInstance
指定类加载器
、需要代理的类接口
及执行代理类中方法的执行器
执行代理类中方法的执行器
需要实现InvocationHandler
接口,执行调用逻辑
Proxy : 负责动态生成代理
- newProxyInstance
- ClassLoader 被代理类的类加载器
- Class<?>[] 代理类要实现的接口
- InvocationHandler 代理类中需要加入的功能
InvocationHandler:代理类新增的功能
- invoke
- Object proxy 代理的实例
- Method 被拦截的方法
- Object[] args 方法的参数
实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| public class ProxyFactory { public static Object createProxy(Object target){ ClassLoader classLoader = target.getClass().getClassLoader(); Class<?>[] interfaces = target.getClass().getInterfaces(); PerformanceMonitorHandler h = new PerformanceMonitorHandler(target); return Proxy.newProxyInstance(classLoader,interfaces,h); } } public interface NuclearWeaponBoomService { public void startBoom(); }
public class NuclearWeaponBoomServiceImpl implements NuclearWeaponBoomService { @Override public void startBoom() { for (int i = 10; i> 0 ; i--) { System.out.println(i); try { Thread.sleep(1000); }catch (InterruptedException e){ throw new RuntimeException("线程异常",e); } } System.out.println("boom"); } }
public class PerformanceMonitorHandler implements InvocationHandler { private Object target; public PerformanceMonitorHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { long before = System.currentTimeMillis(); Object result = method.invoke(target, args); long after = System.currentTimeMillis(); System.out.println("方法:"+method.getName()+"共执行了:"+(after-before)+"毫秒"); return result; } } public class PerfApp { public static void main(String[] args) { NuclearWeaponBoomService nwbs = new NuclearWeaponBoomServiceImpl(); NuclearWeaponBoomService proxy = (NuclearWeaponBoomService)ProxyFactory.createProxy(nwbs); proxy.startBoom(); } }
|
示例:JDK动态代理实现Redis降级
CGlib动态代理
实习方式
- cglib : code generation lib 代码生成库
- 使用继承的方式来生成代理类
- 代理类继承被代理类,覆盖被代理类的方法,在实现中调用父类的相应方法
实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| public class CglibProxyFactory { public static Object createProxy(Object target){ Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(target.getClass()); enhancer.setCallback(new PerformanceMonitorInterceptor()); return enhancer.create(); } }
public class NuclearWeaponBoomServiceImpl extends Nuclear { public void startBoom() { for (int i = 10; i> 0 ; i--) { System.out.println(i); try { Thread.sleep(1000); }catch (InterruptedException e){ throw new RuntimeException("线程异常",e); } } System.out.println("boom"); } }
public class PerformanceMonitorInterceptor implements MethodInterceptor { @Override public Object intercept(Object target, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { long before = System.currentTimeMillis(); Object result = methodProxy.invokeSuper(target, args); long after = System.currentTimeMillis(); System.out.println("方法:"+method.getName()+"共执行了:"+(after-before)+"毫秒"); return result; } }
public class Nuclear { public void startBoom(){}; }
public class PerfApp { public static void main(String[] args) { Nuclear nwbs = new NuclearWeaponBoomServiceImpl(); Nuclear proxy = (Nuclear)CglibProxyFactory.createProxy(nwbs); proxy.startBoom(); } }
|
JDK、CGlib动态代理的区别
- jdk使用接口的方式实现动态代理
- cglib使用继承的方式实现动态代理
- 性能:jdk1.8之前 cglib 胜出 、 jdk1.8之后 jdk方式胜出
- spring 默认是用jdk动态代理生成代理类,但是也支持cglib