千峰牛逼
動(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() 類加載器,用來(lái)加載代理類
* @param us.getClass().getInterfaces() 被代理的接口
* @param new InvocationHandler() 內(nèi)部類 重寫(xiě)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無(wú)法攔截
代理方法
public class UserFactory {
/**
* 使用Spring中的一個(gè)增強(qiáng)類來(lái)實(shí)現(xiàn)aop方式
* 1. 創(chuàng)建Enhancer對(duì)象
* 2. 設(shè)置增強(qiáng)類Enhancer的superClass
* 3. 設(shè)置Enhancer對(duì)象的回調(diào)
* 4. 通過(guò)eh對(duì)象的create()方法來(lái)得到指定的對(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. 通過(guò)eh對(duì)象的create()方法來(lái)得到指定的對(duì)象
IUserService<Object> ius = (IUserService<Object>) eh.create();
return ius;
}
}
jdk代理方式與cglib代理方式的區(qū)別
JDK代理只能對(duì)實(shí)現(xiàn)了接口的類生成代理,而CGLIB是通過(guò)繼承的方式實(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接口
重寫(xiě)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")
配置代理工廠
<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>