首先看看我们要做什么
@Component
public class UserConfig {
public UserConfig() {
}
@Bean
public VideoModel getVideoModel() {
return new VideoModel();
}
@Bean
public VideoDao getVideoDao(VideoModel video) {
return new VideoDao(video);
}
}
加了Component的类,构造就不是用户来操作了,而是交给本文的工具
加了Bean的方法返回值也会实例化,然后用户要用的时候直接从工厂中拿出来。
缺陷以及硬性要求下面会提及。
1.IOC(控制反转),指在程序设计中,实例不再由程序开发者来创建,而是通过容器(spring)来创建,令控制权由应用代码转移到了外部容器,控制反转。
2.DI依赖注入(组合注入),在使用框架创建对象时,动态的将其所依赖的对象注入bean组件中。举例:ClassA 里有ClassB,因此容器在创建A对象是会把B对象实例化并且注入到A之中。
3.Bean:由容器创建的对象。
4.注解(XML也是可以的,不过太多的Bean会令xml文件显得臃肿,这里使用注解标记bean)
ioc与aop是独立的,ioc完成的主要是bean的创建,bean的注入,aop主要实现在方法前后添加业务。如果需要同时的实现IOC与AOP我们的模型应该封装有原对象与代理对象。
public class MyProxy {
private Object proxy;
private Object object;
//通过递归解决循环依赖注入
private boolean injection;
//方法拦截器一一对应
******* getter and setter*****
}
原对象和代理对象的模型好了。接下来我们需要一个工厂来生产模型。根据class或object生成模型,当然如果利用object生成模型,模型中的object自然与参数相同。
//根据传来的class和object生成代理对象模型,并且添加拦截器方法
public class ProxyFactory {
//重载,获取代理模型对象
public static MyProxy getMyProxy(Object object) {
Class<?> klass = object.getClass();
MyProxy myproxy = new MyProxy();
Object proxy = MakeCGlProxy(klass,object,myproxy);
myproxy.setObject(object);
myproxy.setProxy(proxy);
return myproxy;
}
public static MyProxy getMyProxy(Class<?> klass) {
Object object=null;
try {
object = klass.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return getMyProxy(object);
}
//通过klass和object生成代理对象
@SuppressWarnings("unchecked")
private static <T> T MakeCGlProxy(Class<?> klass,Object object,MyProxy myProxy) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(klass);
enhancer.setCallback(new MethodInterceptor() {
//方法拦截器
@Override
public Object intercept(Object obj, Method method, Object[] paramterlist, MethodProxy arg3) throws Throwable {
//添加拦截器
return doInvoke(klass, object,method ,paramterlist,myProxy);
}
});
return (T) enhancer.create();
}
private static Object doInvoke(Class<?> klass,Object object,Method method,Object[] paramterlist,MyProxy myProxy) {
//TODO 从map中查找出来这个代理需要添加的拦截方法添加在方法调用的前后
Object result=null;
try {
result = method.invoke(object, paramterlist);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
当然,我们以后的拦截器链就会通过方法添加在doInvoke方法中了,相当于给代理添加了拦截方法。
生成的工具类也有了,下一步自然是生成bean工厂来管理这些MyProxy(第一个类)了,这里我们采取恶汉模式,即在包扫描时期就完成全部bean的建立。
public class ProxyBeanFactory {
//Bean and ClassName
private static Map<String, String> beanMap;
//ClassName and MyProxy
private static Map<String, MyProxy> proxyMap;
static {
beanMap=new HashMap<String,String>();
proxyMap = new HashMap<String ,MyProxy>();
}
public static Map<String, MyProxy> getProxyMap() {
return proxyMap;
}
public static Map<String, String> getbeanMap(){
return beanMap;
}
//根据name和classname生成beanMap,之后调用一个方法把klassname和这个klass对应的myProxy生成proxymap
public static void addBeanMap(String name, Class<?> klass) throws CantNewInstanceException, InstantiationException, IllegalAccessException {
if(beanMap.containsKey(name)) {
System.out.println(name+"已经被添加进bean中,可以直接使用");
return;
}
beanMap.put(name, klass.getName());
addProxyMap(klass);
}
public static void addBeanMap(String name,Object object) throws CantNewInstanceException{
Class<?> klass = object.getClass();
if(beanMap.containsKey(name)) {
System.out.println(name+"已经被添加进bean中,可以直接使用");
return;
}
beanMap.put(name, klass.getName());
addProxyMap(object);
}
public static void addProxyMap(Class<?> klass) throws InstantiationException, IllegalAccessException {
Object object = klass.newInstance();
addProxyMap(object);
}
public static void addProxyMap(Object object) {
Class<?> klass = object.getClass();
if(proxyMap.containsKey(klass.getName())) {
System.out.println(klass.getName()+"已经被添加进bean中,可以直接使用");
return;
}
MyProxy myProxy = ProxyFactory.getMyProxy(object);
proxyMap.put(klass.getName(), myProxy);
}
public static void createBean(Class<?> klass) throws CantNewInstanceException {
Object object=null;
try {
object = klass.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new CantNewInstanceException("实例化出错");
}
addProxyMap(object);
return;
}
//根据注解名获得My
public static MyProxy getMyProxyByBeanByClassname(String componentname) {
String classname = beanMap.get(componentname);
if(classname==null) {
System.out.println(classname+"没有加入到bean工厂中");
}
return getMyProxyByClassname(classname);
}
//根据类名获取到MyProxy
public static MyProxy getMyProxyByClassname(String classname) {
return proxyMap.get(classname);
}
//根据注解名获取到类名
public static String getClassNameByName(String name) {
return beanMap.get(name);
}
public static MyProxy getBeanByAnnotation(String annotationname) {
return proxyMap.get(beanMap.get(annotationname));
}
}
就是beanMap和ProxyMap的添加以及获取,beanMap中存放注解名和类名,ProxyMap中存放类名和代理模型。
接下来,我们要通过包扫描生成我们的map了。思路与缺陷如下:
1,带Component注解的类需要包含一个无参构造。(缺陷1,如果带Component的类没有无参构造,崩溃)
2.通过带参数函数的返回值加入bean时要求参数在方法调用前生成bean,否则崩溃,这就对方法的顺序有了一些限定了。
这是包扫描形成map来管理bean的类,说一下思想,首先包扫描,如果这个类带了Component注解,那么使用NewInstance来进行构造,并且加入Bean工厂(就是那上述两个map),接着扫描这个类的方法,带了bean注解无参方法直接调用,把返回值加入bean,有参数的先管理起来
public class SomeParamterMethod {
private Method method;
private Object object;
private String name;
public SomeParamterMethod(Method method,
Object object,String name) {
this.method = method;
this.object = object;
this.name = name;
}
就这样管理就行。等到包扫描完成了,这个带参方法参数的bean都在工厂了,拿出来调用一下然后直接调用方法获取返回值且加入bean。控制反转就得到了体现
public class BeanFactory {
public static void scanerPackage(String packagename) throws CantNewInstanceException {
List<SomeParamterMethod> methodlist = new ArrayList<SomeParamterMethod>();
new PackageScanner() {
@Override
public void dealClass(Class<?> klass) {
try {
makeBeanFactory(klass,methodlist);
} catch (CantNewInstanceException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}.packageScan(packagename);
//完成了扫描,此时含参函数的参数值应该都已经在Bean工厂之中
for(SomeParamterMethod spm : methodlist) {
//带参数的函数获取实例化返回值
Object result = dealSomeParamterMethod(spm);
createBean(result, spm.getName());
}
}
//检查该类是否有注解
private static void makeBeanFactory(Class<?> klass,List<SomeParamterMethod> methodlist) throws CantNewInstanceException, InstantiationException, IllegalAccessException {
if(!klass.isAnnotationPresent(Component.class)) {
return;
}
// 表明带有注解,加入生成该类的代理对象
Component annotation = klass.getAnnotation(Component.class);
String name = annotation.name();
createBean(klass, name);
MyProxy myProxy = ProxyBeanFactory.getMyProxyByClassname(klass.getName());
Object object = myProxy.getObject();
Method[] methods = klass.getMethods();
for(int i=0;i<methods.length;i++)
{
Method method=methods[i];
if( !method.isAnnotationPresent(Bean.class)) {
continue;
}
Bean bean = method.getAnnotation(Bean.class);
String methodname = bean.name();
//对方法处理,不带参数的直接调用,把返回值加入bean,带参数的扔到list里头
dealMethod(method,klass,methodname,methodlist,object);
}
}
private static void dealMethod(Method method,Class<?> klass,String methodname,
List<SomeParamterMethod> methodlist,Object object) throws CantNewInstanceException {
//无参数的方法
if(method.getParameters().length==0) {
Object InBean = null;
try {
InBean = method.invoke(object);
createBean(InBean, methodname);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
}
else {
//有参函数,加入队列之中
methodlist.add(new SomeParamterMethod(method, object, methodname));
}
}
//此方法用来把对象实例后加入bean
private static void createBean(Class<?> klass,String name) throws CantNewInstanceException, InstantiationException, IllegalAccessException {
if(name.length()>0) {
ProxyBeanFactory.addBeanMap(name, klass);
}
else {
ProxyBeanFactory.addProxyMap(klass);
}
}
private static void createBean(Object object,String name) throws CantNewInstanceException{
if(name.length()>0) {
ProxyBeanFactory.addBeanMap(name, object);
}
else {
ProxyBeanFactory.addProxyMap(object);
}
}
//处理带参数的函数
private static Object dealSomeParamterMethod(SomeParamterMethod spm) {
// 这里头的Object是从bean工厂里拿出来的Object
Method method = spm.getMethod();
Parameter[] parameters = method.getParameters();
Object result = null;
Object object = spm.getObjcet();
Object[] paramterObjects = new Object[parameters.length];
for(int i=0;i<parameters.length;i++) {
Parameter parameter = parameters[i];
MyProxy mp= ProxyBeanFactory.getMyProxyByBeanByClassname(parameter.getType().getName());
Object args = mp.getObject();
paramterObjects[i] = args;
}
try {
result = method.invoke(object, paramterObjects);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
//根据注解名获取bean工厂里头的bean,应该是代理对象,只有代理对象才能完成aop操作,在此时应该完成依赖注入
@SuppressWarnings("unchecked")
public static <T> T getBean(Class<?> klass) {
MyProxy myproxy= ProxyBeanFactory.getMyProxyByClassname(klass.getName());
if(myproxy.isInjection()==false) {
//对模型注入
inJection(myproxy);
}
return (T)myproxy.getProxy();
}
private static void inJection(MyProxy myproxy) {
Object object = myproxy.getObject();
Class<?> klass = object.getClass();
Field[] fields = klass.getDeclaredFields();
for(int i=0;i<fields.length;i++) {
Field field = fields[i];
if(!field.isAnnotationPresent(Autowired.class)) {
continue;
}
String name = field.getType().getName();
MyProxy myp = ProxyBeanFactory.getMyProxyByClassname(name);
Object injectObj = myp.getObject();
//还没有注入,递归
if(myproxy.isInjection()==false) {
myproxy.setInjection(true);
inJection(myp);
}
//这个带注解,表示需要自动装入
field.setAccessible(true);
try {
field.set(object, injectObj);
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
讲一下最后两个函数,这里用来解决依赖注入,所以我们发现,注入的时期是用户第一次从bean中要取出对象的时候(自然是代理对象,不然无法完成aop),对原对象进行注入,取出来的是代理对象,但是要求对原对象注入,为了解决循环依赖注入造成死循环,我们在myproxy中的Injection属性就起到了作用,我们采取递归解决,对带注解的成员进行赋值,用injection来确认这个是否已经完成成员属性的注入,这就解决了死循环问题。
测试
三个测试类,A中有B,B中有C,C中有A
public class Test {
public static void main(String[] args) throws CantNewInstanceException {
BeanFactory.scanerPackage("com.mec.student");
//IntercepterScanner.intercepterScanner("com.mec.student");
//拿到了代理对象
ClassA a = BeanFactory.getBean(ClassA.class);
System.out.println(a);
ClassB b = a.getClassb();
System.out.println(b);
ClassC c = b.getClassc();
System.out.println(c);
ClassA a2 = c.getClassa();
System.out.println(a2);
System.out.println(a.hashCode()+" : "+a2.hashCode());
}
}
我们看一下结果。
这不是new出来的,是从bean工厂中取出来的,这就说明了我们成功完成了IOC,单例的实现了bean工厂,多例模式在接下来会继续讨论。
AOP:首先让我们看看需要做什么事
@Aspect
public class StudentLogger {
public StudentLogger() {
}
@Before(klass=ClassA.class, method="getClassb")
public boolean beforegetClassb(int args1,String args2) {
System.out.println("置前拦截到参数 : "+args1+" "+args2);
return true;
}
@After(klass=ClassA.class,
method="getClassb",
parameterTypes= { int.class ,String.class })
public ClassB aftergetClassb(ClassB b) {
System.out.println("后置拦截倒了对象" + b.getClass());
return b;
}
@Before(klass=ClassA.class, method="getClassb")
public boolean getClassb(int args1,String args2) {
System.out.println("第二次前置拦截!");
return true;
}
@Before(klass=ClassA.class, method="getClassb")
public boolean beforegetClassb2(int args1,String args2) {
System.out.println("对DAO的拦截:" + args1);
return true;
}
}
我们要做的是:1,让这些加了注解的方法在被拦截方法前后调用,
2,拦截的方法已经写在了注解里面,根据注解信息给类加拦截。
其实思路一样,先包扫描一波,把信息抽象成模型管理,然后再代理那里写个方法,把是对这个对象添加拦截的方法找出来,前置拦截前置调用,后置拦截后置调用。
好了,大体框架出来了,我们细想一下该把信息怎么抽象出来,拦截方法和被拦截方法应该是什么关系, 是我们写一个带注解的拦截方法就能拦截许多被拦截方法?
是一对多,多对一,还是多对多。你是对一个类添加20个拦截的机会多还是对20个类添加一个拦截机会多呢?其实都很多,这要根据具体需求来定了,小编只在这里讲述一下一对一的处理,因为一对多,多对一,多对多对注解的信息要求就需要程序员自己来定了,一对一是最简单的,易于理解。
开始代码吧,首先来个工厂来管理这些拦截方法
public class IntercepterFactory {
//这个类的什么方法被添加了什么拦截方法,这两个模型在下面讲解
private static final Map<IntercepterTargetDefination, List<IntercepterMethodDefination>> beforeMap;
private static final Map<IntercepterTargetDefination, List<IntercepterMethodDefination>> afterMap;
private static final Map<IntercepterTargetDefination, List<IntercepterMethodDefination>> exceptionMap;
static {
beforeMap = new HashMap<>();
afterMap = new HashMap<>();
exceptionMap = new HashMap<>();
}
protected IntercepterFactory() {
}
private void addIntercepter(
Map<IntercepterTargetDefination, List<IntercepterMethodDefination>> map,
IntercepterTargetDefination interTarget,
IntercepterMethodDefination intercepter) {
List<IntercepterMethodDefination> methodList = map.get(interTarget);
if (methodList == null) {
synchronized (IntercepterFactory.class) {
if (methodList == null) {
methodList = new ArrayList<>();
map.put(interTarget, methodList);
}
}
}
methodList.add(intercepter);
}
protected void addBeforeIntercepter(IntercepterTargetDefination interTarget,
IntercepterMethodDefination intercepter) {
addIntercepter(beforeMap, interTarget, intercepter);
}
protected void addAfterIntercepter(IntercepterTargetDefination interTarget,
IntercepterMethodDefination intercepter) {
addIntercepter(afterMap, interTarget, intercepter);
}
protected void addExceptionIntercepter(IntercepterTargetDefination interTarget,
IntercepterMethodDefination intercepter) {
addIntercepter(exceptionMap, interTarget, intercepter);
}
protected List<IntercepterMethodDefination> getBeforeIntercepterList(
IntercepterTargetDefination interTarget) {
return beforeMap.get(interTarget);
}
protected List<IntercepterMethodDefination> getAfterIntercepterList(
IntercepterTargetDefination interTarget) {
return afterMap.get(interTarget);
}
protected List<IntercepterMethodDefination> getExceptionIntercepterList(
IntercepterTargetDefination interTarget) {
return exceptionMap.get(interTarget);
}
}
键是确定要拦截的类,值是具体的拦截方法。三个map,分别存储前后置和异常。
这是值,什么类的什么方法要被拦截时的具体方法
public class IntercepterMethodDefination {
private Class<?> klass;
private Method method;
private Object object;
IntercepterMethodDefination() {
}
IntercepterMethodDefination(Class<?> klass, Method method, Object object) {
this.klass = klass;
this.method = method;
this.object = object;
}
********getter and setter****
}
键被拦截的方法
public class IntercepterTargetDefination {
private Class<?> klass;
private Method method;
public IntercepterTargetDefination(Class<?> klass, Method method) {
this.klass = klass;
this.method = method;
}
}
模型好了,我们分析一下拦截方法和被拦截方法之间的联系吧。
前置:前置拦截方法返回值应该是boolean类型的,来确定是否要拦截,参数应该和被拦截方法的一样,以便于做一些操作,等于在函数调用前就把参数拿过来做一些处理。在开发中,拦截方法和被拦截方法应该都是用户来编写的。
后置:自然是对被拦截方法的返回值处理一下再返回了。
异常:看用户自己了。
好了知道有什么限制了,包扫描生成工厂
public class IntercepterScanner {
public IntercepterScanner() {
}
//通过包扫描扫描出带@after @befor @throwException的方法,加入我们的bean之中
public static void intercepterScanner(String packageName) {
new PackageScanner() {
@Override
public void dealClass(Class<?> klass) {
if (!klass.isAnnotationPresent(Aspect.class)) {
return;
}
try {
Object object = klass.newInstance();
Method[] methods = klass.getDeclaredMethods();
for (Method method : methods) {
try {
//根据不同的方法注解,添加到不同的数据仓库里头。
if (method.isAnnotationPresent(Before.class)) {
//前置拦截
Before before = method.getAnnotation(Before.class);
dealBeforeInterceptor(klass, object, method, before);
} else if (method.isAnnotationPresent(After.class)) {
//后置拦截
After after = method.getAnnotation(After.class);
dealAfterInterceptor(klass, object, method, after);
} else if (method.isAnnotationPresent(ThrowException.class)) {
//错误拦截
ThrowException throwException = method.getAnnotation(ThrowException.class);
dealExceptionInterceptor(klass, object, method, throwException);
}
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.packageScan(packageName);
}
private static void dealBeforeInterceptor(Class<?> klass, Object object,
Method method, Before before) throws Exception {
// 前置拦截器方法的返回值必须是boolean
// 前置拦截器方法的参数必须是Object[],事实是相关方法的实参,就是说前置拦截方法的参数就是被拦截方法的参数
// 若不满足上述要求,应该抛出异常。
Class<?> returnType = method.getReturnType();
if (!returnType.equals(boolean.class)) {
throw new Exception("前置拦截器("
+ method + ")返回值类型只能是boolean");
}
Class<?> targetKlass = before.klass();
Method targetMethod = targetKlass.getMethod(before.method(),
method.getParameterTypes());
IntercepterMethodDefination imd = new IntercepterMethodDefination(
klass, method, object);
IntercepterTargetDefination itd = new IntercepterTargetDefination(targetKlass, targetMethod);
IntercepterFactory intercepterFactory = new IntercepterFactory();
intercepterFactory.addBeforeIntercepter(itd, imd);
}
private static void dealAfterInterceptor(Class<?> klass, Object object,
Method method, After after) throws Exception {
// 后置拦截器方法的返回值必须是Object
// 后置拦截器方法的参数必须是Object,事实是相关方法的实参
// 若不满足上述要求,应该抛出异常。
Class<?> intercepterReturnType = method.getReturnType();
Class<?> targetKlass = after.klass();
Method targetMethod = targetKlass.getMethod(after.method(),
after.parameterTypes());
Class<?> targetReturnType = targetMethod.getReturnType();
if (!intercepterReturnType.equals(targetReturnType)) {
throw new Exception("后置拦截器("
+ method + ")的返回值类型不是" + targetReturnType);
}
IntercepterMethodDefination imd = new IntercepterMethodDefination(
klass, method, object);
IntercepterTargetDefination itd = new IntercepterTargetDefination(targetKlass, targetMethod);
IntercepterFactory intercepterFactory = new IntercepterFactory();
intercepterFactory.addAfterIntercepter(itd, imd);
}
private static void dealExceptionInterceptor(Class<?> klass, Object object,
Method method, ThrowException throwException) throws Exception {
// 异常拦截器方法的返回值必须是void
// 异常拦截器方法的参数必须是Throwable,事实是相关方法的实参
// 若不满足上述要求,应该抛出异常。
Class<?> returnType = method.getReturnType();
if (!returnType.equals(void.class)) {
throw new Exception("异常拦截器("
+ method + ")返回值类型只能是void");
}
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length != 1 || !parameterTypes[0].equals(Throwable.class)) {
throw new Exception("异常拦截器("
+ method + ")形参类型只能是Throwable");
}
Class<?> targetKlass = throwException.klass();
Method targetMethod = targetKlass.getMethod(throwException.method(), Throwable.class);
IntercepterMethodDefination imd = new IntercepterMethodDefination(
klass, method, object);
IntercepterTargetDefination itd = new IntercepterTargetDefination(targetKlass, targetMethod);
IntercepterFactory intercepterFactory = new IntercepterFactory();
intercepterFactory.addBeforeIntercepter(itd, imd);
}
}
这里没什么难点,就是把对应的数据封装到各自的对象中,在分类扔在map里就行了。只要弄清楚了拦截方法和被拦截方法的区别,这里就很容易了。
工厂又好了,接下来就是考虑怎么加了,拦截嘛,自然要加在代理生成的时候,代理里的api有刚刚好有method,那就是根据method来找到拦截的方法了。
public class DoIntercepter {
//这个method是被拦截的方法
public static boolean doBefore(Class<?> klass, Method method, Object[] args) {
IntercepterFactory intercepterFactory = new IntercepterFactory();
//生成键
IntercepterTargetDefination itd = new IntercepterTargetDefination(klass, method);
//根据键找到了这个方法的所有拦截方法
List<IntercepterMethodDefination> intercepterList =
intercepterFactory.getBeforeIntercepterList(itd);
if (intercepterList == null) {
return true;
}
//逐个调用拦截方法
for (IntercepterMethodDefination imd : intercepterList) {
Method intercepterMethod = imd.getMethod();
Object intercepterObject = imd.getObject();
boolean result = false;
try {
//调用加了注释的拦截器方法
result = (Boolean) intercepterMethod.invoke(intercepterObject, args);
} catch (Exception e) {
e.printStackTrace();
}
if (result == false) {
return false;
}
}
return true;
}
public static Object doAfter(Class<?> klass, Method method, Object result) {
IntercepterFactory intercepterFactory = new IntercepterFactory();
IntercepterTargetDefination itd = new IntercepterTargetDefination(klass, method);
List<IntercepterMethodDefination> intercepterList =
intercepterFactory.getAfterIntercepterList(itd);
if (intercepterList == null) {
return result;
}
for (IntercepterMethodDefination imd : intercepterList) {
Method intercepterMethod = imd.getMethod();
Object intercepterObject = imd.getObject();
try {
result = intercepterMethod.invoke(intercepterObject, result);
} catch (Exception e) {
e.printStackTrace();
}
}
return result;
}
public static void doException(Class<?> klass, Method method, Throwable th) {
IntercepterFactory intercepterFactory = new IntercepterFactory();
IntercepterTargetDefination itd = new IntercepterTargetDefination(klass, method);
List<IntercepterMethodDefination> intercepterList =
intercepterFactory.getExceptionIntercepterList(itd);
if (intercepterList == null) {
return;
}
for (IntercepterMethodDefination imd : intercepterList) {
Method intercepterMethod = imd.getMethod();
Object intercepterObject = imd.getObject();
try {
intercepterMethod.invoke(intercepterObject, th);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
上述代码重复性极高,但小编还没有找到合适的解决思路,因为参数不一样,调用不一样,看似差不多,但哪哪都不一样,搞得抽取很难,如果您有好的建议请提出,感谢。
最后一部:扔到代理生成那里去
public class ProxyFactory {
//重载,获取代理模型对象
public static MyProxy getMyProxy(Object object) {
Class<?> klass = object.getClass();
MyProxy myproxy = new MyProxy();
Object proxy = MakeCGlProxy(klass,object);
myproxy.setObject(object);
myproxy.setProxy(proxy);
return myproxy;
}
public static MyProxy getMyProxy(Class<?> klass) {
Object object=null;
try {
object = klass.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return getMyProxy(object);
}
//通过klass和object生成代理对象
@SuppressWarnings("unchecked")
private static <T> T MakeCGlProxy(Class<?> klass,Object object) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(klass);
MethodInterceptor methodInterceptor =new MethodInterceptor() {
//方法拦截器
@Override
public Object intercept(Object obj, Method method, Object[] paramterlist, MethodProxy arg3) throws Throwable {
//添加拦截器
return doInvoke(klass, object,method ,paramterlist);
}
};
enhancer.setCallback(methodInterceptor);
return (T) enhancer.create();
}
private static Object doInvoke(Class<?> klass,Object object,Method method,Object[] paramterlist) {
//TODO 从map中查找出来这个代理需要添加的拦截方法添加在方法调用的前后
Object result=null;
if (DoIntercepter.doBefore(klass, method, paramterlist) == false) {
return null;
}
try {
result = method.invoke(object, paramterlist);
// 后置拦截
DoIntercepter.doAfter(klass, method, result);
} catch (Throwable e) {
// 异常拦截
e.printStackTrace();
DoIntercepter.doException(klass, method, e);
}
return result;
}
}
最后一波测试
public static void main(String[] args) throws CantNewInstanceException {
BeanFactory.scanerPackage(“com.mec.student”);
IntercepterScanner.intercepterScanner(“com.mec.student”);
//拿到了代理对象
ClassA a = BeanFactory.getBean(ClassA.class);
ClassB b = a.getClassb(2,“46546”);
}
没问题呀,完成了aop与ioc了。
当然这里还有细节可以增强,比如多例模式的,这些东西不难,但实现起来过于庞杂和扣细节,我们只要知道了实现的原理,细节可以通过后天的慢慢思索来进行修改和操作,本文结束。
指导老师:微易码