Spring AOP-手动代理

 代理模式是java中常用的设计模式,代理类通过调用被代理类的相关方法,提供预处理,过滤,事后处理等服务。AOP手动使用代理模式有两个典型的例子,分别为JDK动态代理和CGLIB代理。

 项目用到的Junit 项目右键-properties-java build path - library -add library - Junit

一,JDK动态代理

 JDK动态代理是通过JDK中的java.lang.reflect.Proxy 类来实现的,下面通过一个案例来说明

1,在eclipse或myeclipse下创建一个web项目导入spring项目所需的jar包

2,在src目录下创建一个包cn.itcast.dao,在改包下创建一个接口UserDao

package cn.itcast.dao;

public interface UserDao {
	public void save();
	public void update();
	public void delete();
	public void find();
}
 然后在该包下创建接口的实现类UserDaoImpl

package cn.itcast.dao;

public class UserDaoImpl implements UserDao {

	@Override
	public void save() {
		System.out.println("save 添加用户");
	}

	@Override
	public void update() {
		System.out.println("update 更新用户");
	}

	@Override
	public void delete() {
		System.out.println("delete 删除用户");
	}

	@Override
	public void find() {
		System.out.println("find 查找用户");
	}

}
3,在src目录下创建包cn.itcast.jdk 在改包下创建切面类MyAspect


package cn.itcast.jdk;

public class MyAspect {
	public void myBefore(){
		System.out.println("方法执行前");
	}
	public void myAfter(){
		System.out.println("方法执行后");
	}
}
4,在cn.itcast.jdk包下创建MyBeanFactory类在该类中通过Proxy实现动态代理

package cn.itcast.jdk;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import cn.itcast.dao.UserDao;
import cn.itcast.dao.UserDaoImpl;

public class MyBeanFactory {
	public static UserDao getBean(){
		final UserDao userDao = new UserDaoImpl();
		final MyAspect myAspect = new MyAspect();
		return (UserDao)Proxy.newProxyInstance(
				MyBeanFactory.class.getClassLoader(),
				new Class[]{UserDao.class}, 
				new InvocationHandler() {
					
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						//增强前
						myAspect.myBefore();
						//目标类的方式
						Object obj = method.invoke(userDao, args);
						//增强后
						myAspect.myAfter();
						return obj;
					}
				});
	}
}


5,在cn.itcast.jdk包下创建测试类TestJDK

package cn.itcast.jdk;

import org.junit.Test;

import cn.itcast.dao.UserDao;

public class TestJDK {
	@Test
	public void demo(){
		//从工厂获取bean
		UserDao userDao = MyBeanFactory.getBean();
		
		userDao.save();
		userDao.update();
		userDao.delete();
		userDao.find();
	}
}
运行测试方法demo:


JDK动态代理已经实现

二,CGLIB代理

 JDK动态代理用起来非常简单,但是它是有局限性的,使用JDK动态代理的对象必须实现一个或多个接口,如果想代理没有实现接口的类,那么可以使用CGLIB代理

 CGLIB是一个高性能开源的代码生成包,他的底层通过使用一个小而快的字节码处理框架ASM来转换字节码,

为一个类创建子类,然后对子类进行增强,解决了无接口代理。所以CGLIB要依赖ASM的包,但是spring核心包

已经为我们集成CGLIB所需的包,所以我们不需在导入ASM的包,下面通过案例来说明

 1,在上面项目的cn.itcast.dao包下创建类BookDao

package cn.itcast.dao;

public class BookDao {
	public void save() {
		System.out.println("save 添加图书");
	}

	public void update() {
		System.out.println("update 更新图书");
	}

	public void delete() {
		System.out.println("delete 删除图书");
	}

	public void find() {
		System.out.println("find 查找图书");
	}
}
 2,在src目录下创建包cn.itcast.cglib,在该包下创建类MyBeanFactory

package cn.itcast.cglib;


import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import cn.itcast.dao.BookDao;
import cn.itcast.jdk.MyAspect;

public class MyBeanFactory {
	public static BookDao getBean(){
		final BookDao bookDao = new BookDao();
		final MyAspect myAspect = new MyAspect();
		//核心类
		Enhancer enhancer = new Enhancer();
		//确定需要增强的类
		enhancer.setSuperclass(bookDao.getClass());
		//添加回调函数
		enhancer.setCallback(new MethodInterceptor() {
			//interceptor相当于jdk的invoke
			@Override
			public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
				//之前
				myAspect.myBefore();
				
				//目标方法执行
				Object obj = arg1.invoke(bookDao, arg2);
				
				//之后
				myAspect.myAfter();
 				return obj;
			}
		});
		//创建代理类
		BookDao bookDaoProxy = (BookDao)enhancer.create();
		return bookDaoProxy;
	}
	
}
3,在cn.itcast.cjlib包下创建测试类TestCGLIB

package cn.itcast.cglib;

import org.junit.Test;

import cn.itcast.dao.BookDao;

public class TestCGLIB {
	@Test
	public void demo(){
		//从工厂获取bean
		BookDao bookDao = MyBeanFactory.getBean();
		
		bookDao.save();
		bookDao.update();
		bookDao.delete();
		bookDao.find();
	}
}

运行测试方法:



CGLIB代理已经实现









发布了110 篇原创文章 · 获赞 76 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/qq_34731703/article/details/79214970