1、代理模式简介
- 代理模式好比帮你处理其他琐碎事情的类,比如小明要结婚,那他可以找个婚庆公司帮助他干一些布置婚礼现场,婚礼前的一些准备,和婚礼后的一些准备,而婚庆公司就相当于一个代理!
- 说白了就是相当于一个代理对象帮你添加额外的功能,比如说加日志,加事务等!
2、代理模式的分类
- 静态代理
- 动态代理
3、静态代理
public class Demo_07 {
public static void main(String[] args) {
// 创建一个真实对象 人You you = new You();// 创建一个代理对象 婚庆公司WeddingCompany weddingCompany = new WeddingCompany(you);weddingCompany.HappyMarry();}
}// 结婚的接口
interface Marrry {
void HappyMarry();
}class You implements Marrry {
@Overridepublic void HappyMarry() {
System.out.println("田老师要结婚了!");}
}//婚庆公司 相当于一个静态代理
class WeddingCompany implements Marrry {
private You you = null;public WeddingCompany(You you) {
this.you = you;}@Overridepublic void HappyMarry() {
before();you.HappyMarry();after();}public static void before() {
System.out.println("结婚之前布置现场");}public static void after() {
System.out.println("结婚之后收尾款");}
}
4、动态代理
4.1、JDK动态代理
-
编写代理
public class UserHandle implements InvocationHandler { private Object targetObject;// 获取代理类public Object newProxyInstance(Object targetObject) { System.out.println("proxy" + targetObject);this.targetObject = targetObject;return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),targetObject.getClass().getInterfaces(),this);}// 添加额外操作@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object ret = null;System.out.println("正在进行操作前的准备----");ret = method.invoke(targetObject, args);System.out.println("操作成功!");return ret;} }
-
测试
@Test public void addTest() { User user = new User();user.setUsername("动态代理!");// 要代理对象UserService userService = new UserServiceImpl();// 获取代理对象UserHandle userHandle = new UserHandle();UserService userServiceProxy = (UserService) userHandle.newProxyInstance(userService);// 代理对象调用真实方法userServiceProxy.addUser(user); }
4.2、CGLib动态代理
-
创建代理
public class UserCGlibHandle implements MethodInterceptor { private Object targetObject;// 获取目标对象public UserCGlibHandle(Object targetObject) { this.targetObject = targetObject;}// 获取代理类public Object createProxy() { //字节码增强技术Enhancer enhancer = new Enhancer();//设置代理类的父类是目标类enhancer.setSuperclass(targetObject.getClass());//设置回调enhancer.setCallback(this);return enhancer.create();}@Overridepublic Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object ret = null;// 编写自己要添加的业务// 增删改需要开始事务if (method.getName().equals("insertUser") ||method.getName().equals("deleteUser") ||method.getName().equals("updateUser")) { System.out.println("假装开启了事务");ret = method.invoke(this.targetObject, args);System.out.println("假装提交了事务");} else { ret = method.invoke(this.targetObject, args);}return ret;} }
-
测试
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration({ "classpath:applicationContext.xml"}) public class UserHandleTest { @Autowiredprivate UserService userService;@Testpublic void cgLibTest() { UserCGlibHandle userCGlibHandle = new UserCGlibHandle(userService);UserService userServiceProxy = (UserService) userCGlibHandle.createProxy();int i = userServiceProxy.deleteUser(2);System.out.println(i);List<User> users = userServiceProxy.selectByAll();for (User user : users) { System.out.println(user);}} }
小结:
-
CGlib动态代理可以代理实现类!
-
JDK动态代理只能代理接口!
5、小结
- 静态代理通常只代理一个类,动态代理会代理接口中的实现类!
- 静态代理在编译的时候就知道了要代理谁,动态代理在运行的时候才知道要代理谁!
- spring aop即使用了动态代理,也使用了静态代理!