動(dòng)態(tài)代理
-
jdk代理方式
-
新建接口
public interface IUserService<T> { /** * 獲取所有的用戶對(duì)象列表 * @return */ List<T> getAllUser(); /** * 保存用戶 * @param user * @return */ boolean saveUser(T user); /** * 根據(jù)用戶uid刪除該uid對(duì)應(yīng)的用戶信息 * @param uid * @return */ boolean deleteUser(int uid); /** * 更新指定用戶信息 * @param obj * @return */ boolean updateUser(T obj); }
實(shí)現(xiàn)接口
-
實(shí)現(xiàn)代理方法
public class UserFactory { public static IUserService getUserService(){ IUserService us = new UserservcieImpl();//被代理的對(duì)象 MyAspect ma = new MyAspect();//需要添加的代理 /** * @param UserFactory.class.getClassLoader() 類加載器,用來加載代理類 * @param us.getClass().getInterfaces() 被代理的接口 * @param new InvocationHandler() 內(nèi)部類 重寫invoke方法 */ IUserService ius = (IUserService) Proxy.newProxyInstance(UserFactory.class.getClassLoader() , us.getClass().getInterfaces(), new InvocationHandler() { /** * 代理對(duì)象調(diào)用的回掉方法 * @param proxy 代理對(duì)象 * @param method 被代理的方法 * @param args 被代理方法的參數(shù)列表對(duì)象 * @return 每個(gè)方法的最終返回值 * @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生成原有類的子類,設(shè)置好回掉(callback),那么原有類的所有方法都會(huì)被攔截然后調(diào)用實(shí)現(xiàn)了MethodInterceptor的intercept()方法.
- 提示:如果原方法是final類型的,則MethodInterceptor無法攔截
-
代理方法
public class UserFactory { /** * 使用Spring中的一個(gè)增強(qiáng)類來實(shí)現(xiàn)aop方式 * 1. 創(chuàng)建Enhancer對(duì)象 * 2. 設(shè)置增強(qiáng)類Enhancer的superClass * 3. 設(shè)置Enhancer對(duì)象的回調(diào) * 4. 通過eh對(duì)象的create()方法來得到指定的對(duì)象 * @return */ public static IUserService getUserService(){ // 1. 創(chuàng)建Enhancer對(duì)象 Enhancer eh = new Enhancer(); // 2. 設(shè)置增強(qiáng)類Enhancer的superClass eh.setSuperclass(IUserService.class); IUserService<Object> us = new UserServiceImpl<>();//需要代理的對(duì)象 MyAspect ma = new MyAspect();// // 3. 設(shè)置Enhancer對(duì)象的回調(diào) eh.setCallback(new MethodInterceptor() { /** * Object o:被代理的對(duì)象 * Method method:被攔截的方法 * Object[] objects:被攔截的方法的參數(shù)們 * 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對(duì)象的create()方法來得到指定的對(duì)象 IUserService<Object> ius = (IUserService<Object>) eh.create(); return ius; } }
jdk代理方式與cglib代理方式的區(qū)別
- JDK代理只能對(duì)實(shí)現(xiàn)了接口的類生成代理,而CGLIB是通過繼承的方式實(shí)現(xiàn)代理也可以為實(shí)現(xiàn)了接口的類強(qiáng)制使用
- JDK代理在使用次數(shù)較少時(shí)效率高于CGLIB代理,當(dāng)大量使用時(shí)CGLIB代理更勝一籌.但隨著jdk版本的升級(jí),JDK代理效率不斷提升,到j(luò)dk8時(shí)高于CGLIB代理
spring框架中的動(dòng)態(tài)代理方式
-
創(chuàng)建被代理類接口并實(shí)現(xiàn)接口
-
創(chuàng)建代理類,并實(shí)現(xiàn)MethodInterceptor接口
重寫invoke方法
@Override public Object invoke(MethodInvocation invocation) throws Throwable { before(); // 業(yè)務(wù)處理方法的調(diào)用 Object obj = invocation.proceed(); after(); return obj; }
-
配置beans.xml
分別配置被代理類bean(id="us")和代理類bean(id="my")
-
配置代理工廠
<!-- ProxyFactoryBean代理的FactoryBean對(duì)象运悲,我們現(xiàn)在要代理的是us 包含四個(gè)屬性注入: 1. interfaces: 接口對(duì)象們 <list> <value>com.qfedu.aop03.IUserService</value> <value>com.qfedu.aop03.IUserService</value> <value>com.qfedu.aop03.IUserService</value> </list> 2. target:目標(biāo)對(duì)象绸栅,哪個(gè)對(duì)象將被以代理的方式創(chuàng)建 3. interceptorNames:攔截對(duì)象的名稱洛勉,自定義的MethodInterceptor對(duì)象棒厘,注意它的包結(jié)構(gòu)組成 4. optimize:boolean類型的值: true:強(qiáng)制使用cglib的動(dòng)態(tài)代理方式 false:使用jdk自帶的動(dòng)態(tài)代理 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>