千峰牛逼
动态代理
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")
配置代理工厂
<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>