一:前言

  还有<aop:before>/<aop:after>/<aop:around>的没有实现,不过根<aop:advisor>是差不多的,就是要额外注册一些东西到AdvisorSupport里,这个等以后有时间再写了;

二:代码

1.Test类,用于描述<aop:pointcut的expression属性,即调用时这个类中声明的方法不会实施aop拦截

package me.silentdoer.aoprealization.action;

/**
* @author silentdoer
* @version 1.0
* @description the description
* @date 4/28/18 2:50 PM
*/
public class Test {
public void printSS(){
System.out.println("UXXXXXXXXXXXss");
}
}

2.AopTest类,即aspect类(如StudentServiceImpl之类的)

package me.silentdoer.aoprealization.action;

/**
* @author silentdoer
* @version 1.0
* @description 作为pointcut的提供类
* @date 4/27/18 8:14 PM
*/
public class AopTest extends Test{
public void foo(){
System.out.println("Hello, llll");
System.out.println(foo2(88));
} private String foo2(int num){
System.out.println(String.format("The string is %s", num));
return (num + 100) + "";
}
}

3.FooAdviceForAdvisor类,即advisor的实现类

package me.silentdoer.aoprealization.aop.advice;

import net.sf.cglib.proxy.MethodProxy;
import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation; import java.lang.reflect.Method; /**
* @author silentdoer
* @version 1.0
* @description 通过直接实现MethodInterceptor来实现Spring中的<aop:advisor ..></aop:advisor>
* @date 4/27/18 8:32 PM
*/
public class FooAdviceForAdvisor implements MethodInterceptor{
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("Before部分");
//System.out.println(methodInvocation.getClass());
Object result = methodInvocation.proceed();
System.out.println("After部分");
return result;
}
}

4.AopSupport类,实现用户配置和具体产生代理类分离的中间类(around/before/after配置也可以通过这种方式实现)

package me.silentdoer.aoprealization.aop.support;

import me.silentdoer.aoprealization.aop.method.DefaultMethodInvocation;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method;
import java.util.List; /**
* @author silentdoer
* @version 1.0
* @description 这个类在实际中不允许用户主动使用
* @date 4/28/18 2:53 PM
*/
public class AopSupport implements MethodInterceptor {
private List<Method> pointcuts;
private org.aopalliance.intercept.MethodInterceptor advisor; @Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
final Method met = method;
if (this.pointcuts.stream().anyMatch(m -> m.equals(met))){
DefaultMethodInvocation methodInvocation = new DefaultMethodInvocation();
methodInvocation.setTarget(o);
methodInvocation.setMethod(method); // 要通过适配器模式将MethodProxy转换为Method(Method是final无法适配,只好添加MethodProxy属性
methodInvocation.setRealMethod(methodProxy);
methodInvocation.setArgs(objects);
return advisor.invoke(methodInvocation);
}else{
return methodProxy.invokeSuper(o, objects);
}
} public void setPointcuts(List<Method> pointcuts) {
this.pointcuts = pointcuts;
} public void setAdvisor(org.aopalliance.intercept.MethodInterceptor advisor){
this.advisor = advisor;
}
}

5.DefaultMethodInvocation类,用于实现method/args/target的一体化

package me.silentdoer.aoprealization.aop.method;

import net.sf.cglib.proxy.MethodProxy;
import org.aopalliance.intercept.MethodInvocation; import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method; /**
* @author silentdoer
* @version 1.0
* @description the description
* @date 4/28/18 8:38 PM
*/
public class DefaultMethodInvocation implements MethodInvocation{
private Method method;
private MethodProxy realMethod;
private Object[] args;
private Object target; @Override
public Method getMethod() {
return this.method;
} @Override
public Object[] getArguments() {
return this.args;
} @Override
public Object proceed() throws Throwable {
return this.realMethod.invokeSuper(this.target, args);
} @Override
public Object getThis() {
return this.target;
} @Override
public AccessibleObject getStaticPart() {
return this.method;
} public void setMethod(Method method) {
this.method = method;
} public void setArgs(Object[] args) {
this.args = args;
} public void setTarget(Object target) {
this.target = target;
//System.out.println(this.target == null);
} public void setRealMethod(MethodProxy realMethod) {
this.realMethod = realMethod;
}
}

6.main方法所在类,兼具解析xml和装配代理类的作用(demo主要是为了了解aop的实现原理)

package me.silentdoer.aoprealization;

import me.silentdoer.aoprealization.action.AopTest;
import me.silentdoer.aoprealization.aop.advice.FooAdviceForAdvisor;
import me.silentdoer.aoprealization.aop.support.AopSupport;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader; import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List; /**
* @author silentdoer
* @version 1.0
* @description 这里就简单的实现advisor的aop,且expression默认是某个类中所有的declare的方法
* @date 4/27/18 4:56 PM
*/
public class Entrance {
private static Element root;
private static AopTest fooBean; public static void main(String[] args) throws DocumentException, ClassNotFoundException, IllegalAccessException, InstantiationException {
org.dom4j.io.SAXReader reader = new SAXReader();
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Document document = reader.read(classLoader.getResource("aop.xml"));
root = document.getRootElement();
List<Element> elements = root.elements(); Class beanClazz = classLoader.loadClass(elements.stream().filter((e) -> e.attributeValue("id").equals("aopTest")).findFirst().get().attributeValue("class"));
//System.out.println(beanClazz); //me.silentdoer.aoprealization.action.AopTest
// TODO 这个是没有加aop功能时原始的bean,这步可以理解为getBean
fooBean = (AopTest) beanClazz.newInstance();
fooBean.foo(); System.out.println("<------------------------------------------------------->"); // TODO 实现BeanFactoryPostProcessor接口的扫描配置文件来为对应的bean组装aop功能
Element config = elements.stream().filter(e -> e.getName().equals("config")).findFirst().get();
parseAopConfig(config);
// 动态代理类实现aop功能,但是对于非DeclaredMethod不会做切面拦截处理,比如在Test中的printSS方法;
fooBean.foo(); // 实现aop拦截
System.out.println("<---------------------------------------------------------------->");
fooBean.printSS(); // 不符合expression因此即便为fooBean配置了aop对于此方法也不会实施aop功能
} // 根据<aop:config来“重建”需要aop功能的bean,这里就是fooBean
private static void parseAopConfig(Element config){
// TODO 这里认定pointcut的expression是获取originBean的所有的DeclaredMethod方法
Element pointcutElem = config.element("pointcut");
List<Method> pointcuts = parsePointcuts(pointcutElem);
Element advisorElem = config.element("advisor");
// TODO 这里通过advisorElem得到用户自定义的advisor类对象
FooAdviceForAdvisor advisorBean = getUserAdvisor(advisorElem);
// TODO 根据advisor和pointcut组装成一个新的MethodInterceptor对象,这个interceptor是实现了expression和advisor联合的拦截者
MethodInterceptor realInterceptor = parseAdvisor(advisorBean, pointcuts);
// TODO 根据配置得知fooBean是需要加上aop功能,因此通过Enhancer重新生成新的bean覆盖老的bean,这步在Spring里是通过实现了BeanFactoryPostProcessor接口的类里执行的
fooBean = (AopTest) Enhancer.create(AopTest.class, realInterceptor);
} private static MethodInterceptor parseAdvisor(org.aopalliance.intercept.MethodInterceptor advisor, List<Method> pointcuts){
// 正式情况下AdvisorSupport是包访问权限,而这部分代码也是在和此类同一个包里面实现的因此AdvisorSupport是系统组件不由用户手动创建
AopSupport result = new AopSupport();
result.setAdvisor(advisor);
result.setPointcuts(pointcuts);
return result;
} private static List<Method> parsePointcuts(Element aopPointcut){
// TODO 本来应该通过aopPointcut的expression来获取,不过这个主要是实现aop对表达式的解析忽略
return Arrays.asList(AopTest.class.getDeclaredMethods());
} // 根据advisor-ref获取advisor对象
private static FooAdviceForAdvisor getUserAdvisor(Element advisor){
FooAdviceForAdvisor result = new FooAdviceForAdvisor();
return result;
}
}

7.aop.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:aop="silentdoer"> <!-- 模拟注册到Spring里管理,这里则只是简单的通过dom4j来搜索 -->
<bean id="aopTest" class="me.silentdoer.aoprealization.action.AopTest"/> <bean id="fooAdvisor" class="me.silentdoer.aoprealization.aop.advice.FooAdviceForAdvisor"/>
<aop:config>
<!-- 这里暂且认为me.silentdoer.aoprealization.action.AopTest.*就是AopTest中所有Declared的方法 -->
<aop:poincut id="pointcut1" expression="me.silentdoer.aoprealization.action.AopTest.*"/>
<aop:advisor advisor-ref="fooAdvisor" poincut-ref="pointcut1"/>
</aop:config> <!--<bean id="fooAdvice" class="me.silentdoer.aoprealization.aop.advice.FooAdvice"/>
<aop:config>
<aop:pointcut id="pointcut2" expression="me.silentdoer.aoprealization.action.AopTest.*"/>
<aop:aspect ref="fooAdvice">
<aop:around method="around" poincut-ref="poincut2"/>
</aop:aspect>
</aop:config>-->
</beans>

利用cglib包实现Spring中aop的<aop:advisor>功能的更多相关文章

  1. Spring中IOC和AOP的详细解释(转)

    原文链接:Spring中IOC和AOP的详细解释 我们是在使用Spring框架的过程中,其实就是为了使用IOC,依赖注入,和AOP,面向切面编程,这两个是Spring的灵魂. 主要用到的设计模式有工厂 ...

  2. spring中IOC和AOP原理

    IoC(Inversion of Control): (1)IoC(Inversion of Control)是指容器控制程序对象之间的关系,而不是传统实现中,由程序代码直接操控.控制权由应用代码中转 ...

  3. Spring中IOC和AOP的详细解释

    我们是在使用Spring框架的过程中,其实就是为了使用IOC,依赖注入,和AOP,面向切面编程,这两个是Spring的灵魂. 主要用到的设计模式有工厂模式和代理模式. IOC就是典型的工厂模式,通过s ...

  4. 【转】Spring中事务与aop的先后顺序问题

    [原文链接] http://my.oschina.net/HuifengWang/blog/304188 [正文] Spring中的事务是通过aop来实现的,当我们自己写aop拦截的时候,会遇到跟sp ...

  5. spring中的多线程aop方法拦截

    日常开发中,常用spring的aop机制来拦截方法,记点日志.执行结果.方法执行时间啥的,很是方便,比如下面这样:(以spring-boot项目为例) 一.先定义一个Aspect import org ...

  6. 对spring中IOC和AOP的理解

    IOC:控制反转也叫依赖注入.利用了工厂模式. 为了方便理解,分解成每条以便记忆.  1.将对象交给容器管理,你只需要在spring配置文件总配置相应的bean,以及设置相关的属性,让spring容器 ...

  7. Spring中IOC和AOP的理解

    IOC和AOP是Spring的核心 IOC:控制反转:将创建对象以及维护对象之间的关系由代码交给了spring容器进行管理,也就是创建对象的方式反转了,交由spring容器进行管理. DI:依赖注入: ...

  8. 解释Spring中IOC, DI, AOP

    oc就是控制翻转或是依赖注入.通俗的讲就是如果在什么地方需要一个对象,你自己不用去通过new 生成你需要的对象,而是通过spring的bean工厂为你长生这样一个对象.aop就是面向切面的编程.比如说 ...

  9. 利用axure软件实现app中的轮播图功能

    1.首先在axure软件中插入一张手机模型图片并调整为合适大小 2.在需要展示轮播图片位置拖入[动态面板]并且调整大小 拖入后双击动态面板,填入面板名称,并且添加面板状态(此处轮播图为三张,所以有三个 ...

随机推荐

  1. wk1&2 字符串

    [CQ] 自增怎么样都增了,赋值不一定: int x = 2; int y = 2; int i = ++x; int j = y++; System.out.println(x); System.o ...

  2. swift 带有下划线的UIbutton

    import UIKit /// 带下划线的Button class UnderlineButton: JYBaseButton { /// 下划线高度 var underLineHeight:CGF ...

  3. swift - 加速器/摇一摇功能

    import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoa ...

  4. swift - label 的font 设置 文字字体和大小

    设置字体和颜色 lab.textColor = UIColor.init(hexColor: "795928") lab.font = UIFont.systemFont(ofSi ...

  5. C++ 计算直线的交点数(动态规划)

    问题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1466 Problem Description 平面上有n条直线,且无三线共点,问这些直线能有多少种不同 ...

  6. POI依据类型设置导出格式

    //设置Bigdecimal数据导出时以数值形式输出 CellStyle decimalStyle = workbook.createCellStyle(); DataFormat decimalDf ...

  7. 【C++】:STL迭代器使用---[容器::iterator iter;]

    参考文章:http://blog.csdn.net/qq_23100787/article/details/51388163 迭代器这种东西,就是为了使访问简单!! 容器::iterator iter ...

  8. C#中多线程的并行处理

    System.Threading.Tasks,在该命名空间下Task是主类,表示一个类的异步的并发的操作,创建并行代码的时候不一定要直接使用Task类,在某些情况下可以直接使用Parallel静态类( ...

  9. poj 2777(线段树+lazy思想) 小小粉刷匠

    http://poj.org/problem?id=2777 题目大意 涂颜色,输入长度,颜色总数,涂颜色次数,初始颜色都为1,然后当输入为C的时候将x到y涂为颜色z,输入为Q的时候输出x到y的颜色总 ...

  10. php 数组指定位置插入数据单元

      PHP array_splice() 函数 array_splice(array,offset,length,array) 参数 描述 array 必需.规定数组. offset 必需.数值.如果 ...