动态代理
-
jdk代理方式
-
新建接口
public interface IUserService<T> { /** * 获取所有的用户对象列表 * @return */ List<T> getAllUser(); /** * 保存用户 * @param user * @return */ boolean saveUser(T user); /** * 根据用户uid删除该uid对应的用户信息 * @param uid * @return */ boolean deleteUser(int uid); /** * 更新指定用户信息 * @param obj * @return */ boolean updateUser(T obj); }
实现接口
-
实现代理方法
public class UserFactory { public static IUserService getUserService(){ IUserService us = new UserservcieImpl();//被代理的对象 MyAspect ma = new MyAspect();//需要添加的代理 /** * @param UserFactory.class.getClassLoader() 类加载器,用来加载代理类 * @param us.getClass().getInterfaces() 被代理的接口 * @param new InvocationHandler() 内部类 重写invoke方法 */ IUserService ius = (IUserService) Proxy.newProxyInstance(UserFactory.class.getClassLoader() , us.getClass().getInterfaces(), new InvocationHandler() { /** * 代理对象调用的回掉方法 * @param proxy 代理对象 * @param method 被代理的方法 * @param args 被代理方法的参数列表对象 * @return 每个方法的最终返回值 * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { ma.before(); Object obj = method.invoke(us, args);//原方法 ma.after(); return obj; } }); return ius; } }
-
-
cglib代理方式
与jdk代理相似,代理方法有所不同
-
基本原理
- 使用Enhancer生成原有类的子类,设置好回掉(callback),那么原有类的所有方法都会被拦截然后调用实现了MethodInterceptor的intercept()方法.
- 提示:如果原方法是final类型的,则MethodInterceptor无法拦截
-
代理方法
public class UserFactory { /** * 使用Spring中的一个增强类来实现aop方式 * 1. 创建Enhancer对象 * 2. 设置增强类Enhancer的superClass * 3. 设置Enhancer对象的回调 * 4. 通过eh对象的create()方法来得到指定的对象 * @return */ public static IUserService getUserService(){ // 1. 创建Enhancer对象 Enhancer eh = new Enhancer(); // 2. 设置增强类Enhancer的superClass eh.setSuperclass(IUserService.class); IUserService<Object> us = new UserServiceImpl<>();//需要代理的对象 MyAspect ma = new MyAspect();// // 3. 设置Enhancer对象的回调 eh.setCallback(new MethodInterceptor() { /** * Object o:被代理的对象 * Method method:被拦截的方法 * Object[] objects:被拦截的方法的参数们 * MethodProxy methodProxy:MethodProxy类型的被拦截方法 **/ @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { ma.before(); Object obj = method.invoke(us, objects); ma.after(); return obj; } }); // 4. 通过eh对象的create()方法来得到指定的对象 IUserService<Object> ius = (IUserService<Object>) eh.create(); return ius; } }
jdk代理方式与cglib代理方式的区别
- JDK代理只能对实现了接口的类生成代理,而CGLIB是通过继承的方式实现代理也可以为实现了接口的类强制使用
- JDK代理在使用次数较少时效率高于CGLIB代理,当大量使用时CGLIB代理更胜一筹.但随着jdk版本的升级,JDK代理效率不断提升,到jdk8时高于CGLIB代理
spring框架中的动态代理方式
-
创建被代理类接口并实现接口
-
创建代理类,并实现MethodInterceptor接口
重写invoke方法
@Override public Object invoke(MethodInvocation invocation) throws Throwable { before(); // 业务处理方法的调用 Object obj = invocation.proceed(); after(); return obj; }
-
配置beans.xml
分别配置被代理类bean(id="us")和代理类bean(id="my")
-
配置代理工厂
<!-- ProxyFactoryBean代理的FactoryBean对象,我们现在要代理的是us 包含四个属性注入: 1. interfaces: 接口对象们 <list> <value>com.qfedu.aop03.IUserService</value> <value>com.qfedu.aop03.IUserService</value> <value>com.qfedu.aop03.IUserService</value> </list> 2. target:目标对象,哪个对象将被以代理的方式创建 3. interceptorNames:拦截对象的名称,自定义的MethodInterceptor对象,注意它的包结构组成 4. optimize:boolean类型的值: true:强制使用cglib的动态代理方式 false:使用jdk自带的动态代理 cglib:code generation library,代码生成库,性能更高 --> <bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="interfaces" value="com.qfedu.aop03.IUserService" /> <property name="target" ref="us" /> <property name="interceptorNames" value="my" /> <property name="optimize" value="true" /> </bean>