使用Java来实现AOP的功能,主要介绍两种实现方法
- Proxy代理方法
- CGLib方法
1.Proxy代理
- 创建接口
- 创建接口实现类
- 创建代理工厂类
public interface StudentInterface {
public void print();
}
public class StudentBean implements StudentInterface{
private String name;
public StudentBean() {
}
public StudentBean(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void print() {
System.out.println("Hello World!");
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyFactory implements InvocationHandler{
private Object stu;
/**
* 创建目标对象的实体类
* @param stu 目标对象
* @return 目标对象实体类
*/
public Object createStudentProxy(Object stu){
this.stu=stu;
//返回目标对象实体类,第一个参数目标对象的类加载器,第二个参数是目标对象的接口对象,
// 第三个参数是InvocationHandler默认对象。此方法会回调invoke方法
return Proxy.newProxyInstance(stu.getClass().getClassLoader(),stu.getClass().getInterfaces(),this);
}
/**
* 处理业务逻辑:
* 当Student存在名字则直接打印“Hello World”
* 将如Student的名称为空,则输出相关的信息。如“名称为空,代理类已经拦截”等,
* 表明代理类已经起作用了。
*/
public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
StudentBean s= (StudentBean) stu;
Object object=null;
if (s.getName()!=null){
object=method.invoke(stu,args);
}else {
System.out.println("名称为空,代理类已经拦截");
}
return object;
}
}
创建对应入口类来测试代理是否生效
public class Main {
public static void main(String[] args){
StudentInterface s1=new StudentBean();
// StudentInterface s1=new StudentBean("wang");
ProxyFactory factory=new ProxyFactory();
StudentInterface s2= (StudentInterface) factory.createStudentProxy(s1);
s2.print();
}
}
- 目标对象必须实现接口
- 返回创建的代理对象
- 重写接口的invoke()方法
- 限制条件放在invoke()方法中
- asm.jar – CGLIB的底层实现
- cglib.jar – CGLIB的核心jar包。
CGLIB的核心类:
- net.sf.cglib.proxy.Enhancer – 主要的增强类
- net.sf.cglib.proxy.MethodInterceptor – 主要的方法拦截类,它是Callback接口的子接口,需要用户实现
- net.sf.cglib.proxy.MethodProxy – JDK的Java.lang.reflect.Method类的代理类,可以方便的实现对源对象方法的调用,如使用:Object o = methodProxy.invokeSuper(proxy, args);//虽然第一个参数是被代理对象,也不会出现死循环的问题。
- 引入相关jar文件
- 创建实体类
- 创建CGLib代理类
- 创建入口类进行测试
public class StudentBean{
private String name;
public StudentBean() {
}
public StudentBean(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void print() {
System.out.println("Hello World!");
}
}
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* cglib代理工厂类
* 注意实现的接口类是cglib包下的MethodInterceptor
*/
public class CGLibProxyFactory implements MethodInterceptor {
private Object object;
/**
* 创建代理类对象
* @param object 被代理对象
* @return 代理类对象
*/
public Object createStudent(Object object){
this.object=object;
//利用Enhancer来创建代理类
Enhancer enhancer=new Enhancer();
//为目标对象指定父类
enhancer.setSuperclass(object.getClass());
//设置回调函数
enhancer.setCallback(this);
//返回生成的代理类
return enhancer.create();
}
/**
* 业务处理逻辑代码
* 利用到了java的反射
* @param o
* @param method
* @param objects
* @param methodProxy
* @return 代理类对象
* @throws Throwable
*/
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
StudentBean student=(StudentBean)object;
Object result=null;
if (student.getName()!=null){
methodProxy.invoke(object,objects);//利用反射来执行相应的方法
}else{
System.out.println("该方法已被拦截!");
}
return result;
}
}
创建对应的入口类来测试
public class Main {
public static void main(String[] args){
StudentBean student1
= (StudentBean) new CGLibProxyFactory().createStudent(new StudentBean());
StudentBean student2
= (StudentBean) new CGLibProxyFactory().createStudent(new StudentBean("wang"));
student1.print();
student2.print();
}
}
921



被折叠的 条评论
为什么被折叠?



