水平有限,静待各位大佬提出的宝贵的建议。
1.前几天写的aop又看不懂了。再次研究看看重拾记忆。
2.这里创建一个接口,SayHello
public interface SayHello {
String say(String name);
}
3.接口实现类 ManSayHello
public class ManSayHello implements SayHello{
private String name ;
@Override
public String say(String name) {
System.out.println(name+" say : Hello world!");
return name+" is the speaker's name";
}
}
4.AOPHandle
/**
* 此处用到静态代理模式 Object obj 为真实角色(被代理角色);AOPHandle 创建的对象为代理角色
*/
public class AOPHandle implements InvocationHandler {
private Object obj;
AOPHandle(Object obj){
this.obj = obj;
}
@Override
/**
*
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//方法返回值
System.out.println("前置代理");
//反射调用方法
Object ret=method.invoke(obj, args);
//声明结束
System.out.println("后置代理");
//返回反射调用方法的返回值
return ret;
}
}
5.调用此say方法时 运行
package com.iflytek.edu;
import com.iflytek.edu.aop.HelloWorldImpl;
import org.springframework.cglib.proxy.Proxy;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/**
* @author (2084318355@qq.com)
* @Description
* @Time Created on 2019/3/7 10:24.
*/
public class Main {
public static void main(String[] args) throws Throwable {
ManSayHello manSayHello = new ManSayHello();
AOPHandle handle = new AOPHandle(manSayHello);
//下面这段代码实际上生成了一个新的接口实现类的方法??
SayHello sayHello = (SayHello) Proxy.newProxyInstance(SayHello.class.getClassLoader(), new Class[] { SayHello.class }, handle);
String rs = sayHello.say("Linda");
System.out.print(rs);
}
}
6.观察上述代码,在执行 sayHello.say("Linda"); 这段代码时,结果如下
与我们所认识的manSayHello 这个对象的say方法已经产生了差别,原因在于SayHello这个接口在
SayHello sayHello = (SayHello) Proxy.newProxyInstance(SayHello.class.getClassLoader(), new Class[] { SayHello.class }, handle);
这段代码运行完成之后产生了一个新的方法。仔细思考,是只产生一个新的方法,还是为所有方法都产生了新的方法?
7.做个测试,修改SayHello接口,让他多一些新的方法,再让接口实现类实现这些方法。
SayHello
public interface SayHello {
String say(String name);
void hello();
void hi();
}
ManSayHello
public class ManSayHello implements SayHello{
private String name ;
@Override
public String say(String name) {
System.out.println(name+" say : Hello world!");
return name+" is the speaker's name";
}
@Override
public void hello() {
System.out.println("hello");
}
@Override
public void hi() {
System.out.println("hi");
}
}
Main
package com.iflytek.edu;
import com.iflytek.edu.aop.HelloWorldImpl;
import org.springframework.cglib.proxy.Proxy;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/**
* @author 2084318355@qq.com
* @Description
* @Time Created on 2019/3/7 10:24.
*/
public class Main {
public static void main(String[] args) throws Throwable {
ManSayHello manSayHello = new ManSayHello();
AOPHandle handle = new AOPHandle(manSayHello);
//下面这段代码实际上生成了一个新的接口实现类的方法??
SayHello sayHello = (SayHello) Proxy.newProxyInstance(SayHello.class.getClassLoader(), new Class[] { SayHello.class }, handle);
String rs = sayHello.say("Linda");
System.out.println(rs);
sayHello.hello();
sayHello.hi();
}
}
8.结果如下
结果说明刚才的AopHandle生成了一个新的实现类,这个类的所有方法都是由 前置代理+manSayHello的实现方法+后置代理 这三个东西组合到一起的。而在实际当中不可能是为每个方法都 进行这样的操作,因此如何指定特定方法呢?。
9.突然觉得自己傻出新高度!
只要后面调用的对象不是代理生成的新类就行了呀!用之前的对象manSayHello调用方法不就行了吗,如下 hello,hi都是用之前的对象的方法,因此不会出现三个前置代理和后置代理!
至此,完成了调用特定方法时产生的效果。
11.但是这样看不出来面向切面的感觉,后面加以修改:
主要改了AopHandle,对其中的方法名字做检查,让某些方法实现代理(方法重写)。
import org.springframework.cglib.proxy.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
/**
* 此处用到静态代理模式 Object obj 为真实角色(被代理角色);AOPHandle 创建的对象为代理角色
*/
public class AOPHandle implements InvocationHandler {
private Object obj;
AOPHandle(Object obj,List<String> methodName){
this.obj = obj;
this.setMethodName(methodName);
}
AOPHandle(Object obj){
this.obj = obj;
this.setMethodName(methodName);
}
List<String> methodName;
public List<String> getMethodName() {
return methodName;
}
public void setMethodName(List<String> methodName) {
this.methodName = methodName;
}
private Object executeProxy(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
//方法返回值
System.out.println("前置代理");
//反射调用方法
Object ret = method.invoke(obj, args);
//声明结束
System.out.println("后置代理");
//返回反射调用方法的返回值
return ret;
}
@Override
/**
*
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//methodName里面定义所有可以切入的方法
if(methodName!=null&&methodName.size()>0){
int i=0;
while (i < methodName.size()){
if(method.getName().equals(methodName.get(i++))){
return executeProxy(proxy,method,args);
}
}
Object ret=method.invoke(obj, args);
return ret;
}else {
return executeProxy(proxy,method,args); //如果methodName为空 则给所有方法代理
}
}
}
再运行下面的
ManSayHello manSayHello = new ManSayHello();
List<String> methodName = new ArrayList<String>();
methodName.add("say");//此处定义需要被切入的方法
//下面这段代码实际上生成了一个新的接口实现类的所有方法
SayHello sayHello = (SayHello) Proxy.newProxyInstance(SayHello.class.getClassLoader(), new Class[] { SayHello.class }, new AOPHandle(manSayHello,methodName));
String rs = sayHello.say("Linda");
System.out.println(rs);
sayHello.hello();
sayHello.hi();
完美啊!
现在同一个sayHello对象,对应不同的方法中某些方法被代理了,有些没有被代理!
水平有限,静待各位大佬提出的宝贵的建议。