spring系列之aop

面向切面编程时aop的主要特点之一,根据注解找到切面和切入点,然后生成代理对象,又代理对象去执行方法!

注解

annotation

package annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Aspect {

}
 

package annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface PointCut {

    String value();
}

 

容器

aop

package aop;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.tools.ant.util.ReflectUtil;

import annotation.Aspect;
import annotation.PointCut;
import proxy.AbsMethodAdvance;
import utils.ClassUtil;
import utils.ReflectionUtil;

public class ApplicationContext {

    //存放代理类的集合
    public static ConcurrentHashMap<String, Object> proxyBeanMap = new ConcurrentHashMap<String, Object>();
    
    static{
        initAopBeanMap("demo");
    }

    //初始化aop容器
    public static void initAopBeanMap(String basePath){
        try {
            Set<Class<?>> classSet = ClassUtil.getClassSet(basePath);
            for(Class<?> clazz: classSet){
                //找到切面
                if(clazz.isAnnotationPresent(Aspect.class)){
                    Method[] methods = clazz.getMethods();
                    for(Method method: methods){
                        if(method.isAnnotationPresent(PointCut.class)){
                            //获取该方法上的第一个注解
                            PointCut pointCut = (PointCut)method.getAnnotations()[0];
                            String pointCutStr = pointCut.value();    
                            String[] points = pointCutStr.split("_");
                            //被代理的类名
                            String className = points[0];
                            //被代理的方法名
                            String methodName = points[1];
                            //根据切点,创建被代理对象
                            Object targetObj = ReflectionUtil.newInstance(className);//Test
                            //根据切面创建代理者
                            AbsMethodAdvance proxyer = (AbsMethodAdvance)ReflectionUtil.newInstance(clazz);//TestAspect
                            //设置代理方法
                            proxyer.setProxyMthodName(methodName);//doSomething
                            Object object = proxyer.creatProxyObject(targetObj);
                            if(object != null){
                                proxyBeanMap.put(targetObj.getClass().getSimpleName().toLowerCase(), object);
                            }
                        }            
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        
    }
}
 

方法

demo

package demo;

public class Test {

    public void doSomething(){
        System.out.println("do something...");
    }
    
    public void doWithNotProxy(){
        System.out.println("do something with not proxy...");
    }
}

package demo;

import annotation.Aspect;
import annotation.PointCut;
import proxy.AbsMethodAdvance;

@Aspect
public class TestAspect extends AbsMethodAdvance{

    //全类名_方法名
    @PointCut("demo.Test_doSomething")
    public void testAspect(){
        
    }
    
    @Override
    public void doBefore() {
        System.out.println("do Before!");
    }

    @Override
    public void doAfter() {
        System.out.println("do After!");
    }

}

 

代理对象

proxy

package proxy;

import java.lang.reflect.Method;


import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import utils.StringUtils;

public abstract class AbsMethodAdvance implements MethodInterceptor{

    private Object targetObject;//要被代理的对象
    private String proxyMthodName;//要被代理的方法名
    
    /*根据被代理对象,创建代理对象*/
    public Object creatProxyObject(Object target){
        this.targetObject = target;
        //该类用于生成代理对象
        Enhancer enhancer = new Enhancer();
        //设置目标类为代理对象的父类
        enhancer.setSuperclass(this.targetObject.getClass());
        //设置回调对象为本身
        enhancer.setCallback(this);
        return enhancer.create();
    }

    
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        Object result;
        String proxyMethod = getProxyMthodName();
        if(StringUtils.isNotBlank(proxyMethod) && proxyMethod.equals(method.getName())){
            doBefore();
        }
        //执行拦截的方法
        result = proxy.invokeSuper(obj, args);
        
        if(StringUtils.isNotBlank(proxyMethod) && proxyMethod.equals(method.getName())){
            doAfter();
        }
        return result;
    }

    public abstract void doBefore();
    
    public abstract void doAfter();
    
    public String getProxyMthodName() {
        return proxyMthodName;
    }

    public void setProxyMthodName(String proxyMthodName) {
        this.proxyMthodName = proxyMthodName;
    }
    
}

 

工具

utils

package utils;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class ClassUtil {

    //类加载器
    public static ClassLoader getClassLoader(){
        return Thread.currentThread().getContextClassLoader();
    }
    
    /*加载类,需要提供类名与是否需要初始化的标志,初始化是否执行静态代码快*/
    public static Class<?> loadClass(String className,boolean isInitialized){
        Class<?> cls;
        try {
            cls = Class.forName(className, isInitialized, getClassLoader());
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        return cls;
    }
    
    //加载类(默认初始化类)
    public static Class<?> loadClass(String className){
        return loadClass(className,true);
    }
    
    //加载指定包下所有的类
    public static Set<Class<?>> getClassSet(String pakageName) throws IOException{
        Set<Class<?>> classSet = new HashSet<>();
        try {
            Enumeration<URL> urls = getClassLoader().getResources(pakageName.replace(".", "/"));
            while(urls.hasMoreElements()){
                URL url = urls.nextElement();
                if(url != null){
                    String protocol = url.getProtocol();
                    if(protocol.equals("file")){
                        //转码
                        String pakagePath = URLDecoder.decode(url.getFile(), "UTF-8");
                        addClass(classSet,pakagePath,pakageName);
                    }else if(protocol.equals("jar")){
                        JarURLConnection conn = (JarURLConnection)url.openConnection();
                        if(conn != null){
                            JarFile jarFile = conn.getJarFile();
                            if(jarFile != null){
                                Enumeration<JarEntry> entries = jarFile.entries();
                                while(entries.hasMoreElements()){
                                    JarEntry jarEntry = entries.nextElement();
                                    String name = jarEntry.getName();
                                    if(name.endsWith(".class")){
                                        String className = name.substring(0, name.lastIndexOf(".")).replaceAll("/", ".");
                                        doAddClass(classSet,className);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return classSet;
    }

    //添加文件到set集合
    private static void addClass(Set<Class<?>> classSet, String pakagePath, String pakageName) {
        File[] files = new File(pakagePath).listFiles(new FileFilter() {
            
            @Override
            public boolean accept(File file) {
                return (file.isFile() && file.getName().endsWith(".class") || file.isDirectory());
            }
        });
        
        for(File file: files){
            String name = file.getName();
            if(file.isFile()){
                String className = name.substring(0, name.lastIndexOf("."));
                if(StringUtils.isNotBlank(pakageName)){
                    className = pakageName + "." + className;
                }
                doAddClass(classSet, className);
            }else{
                //子目录
                String subPakagePath = name;
                if(StringUtils.isNotBlank(pakagePath)){
                    subPakagePath = pakagePath + "/" + subPakagePath;
                }
                
                String subPakageName = name;
                if(StringUtils.isNotBlank(pakageName)){
                    subPakageName = pakageName + "." + subPakageName;
                }
                addClass(classSet, subPakagePath, subPakageName);
            }
        }
    }
    
    private static void doAddClass(Set<Class<?>> classSet, String className) {
        Class<?> cls = loadClass(className, false);
        classSet.add(cls);
    }
}
 

package utils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectionUtil {

    // 创建实例
    public static Object newInstance(Class<?> cls) {
        Object instance;
        try {
            instance = cls.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        return instance;
    }

    // 根据类名创建实例
    public static Object newInstance(String className) {
        Class<?> clazz = ClassUtil.loadClass(className);
        return newInstance(clazz);
    }
    
    //调用方法
    public static Object invokeMethod(Object obj,Method method,Object... args){
        Object result;
        
        try {
            //允许通过反射访问私有变量
            method.setAccessible(true);
            result = method.invoke(obj, args);
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
        return result;
    }
    
    //设置成员变量的值
    public static void setField(Object obj,Field field,Object value){
        
        try {
            field.setAccessible(true);
            field.set(field, value);
        } catch (IllegalArgumentException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}

 

package utils;

public class StringUtils {

    public static boolean isNotBlank(String str){
        if(str != null && str.trim().length() > 0){
            return true;
        }else{
            return false;
        }
    }
    
    public static boolean isBlank(String str){
        return !isBlank(str);
    }
}
 

主方法

package aop;

import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;

import demo.Test;

public class Main {

    public static void main(String[] args) {
        //模拟容器初始化
        ApplicationContext applicationContext = new ApplicationContext();
        ConcurrentHashMap<String, Object> proxyBeanMap = ApplicationContext.proxyBeanMap;
        //生成的代理对象,默认为类名的小写
        Test test = (Test)proxyBeanMap.get("test");
        test.doSomething();
        System.out.println("-------------");
        test.doWithNotProxy();
    }
}

 

pom文件配置

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.tempus.cn</groupId>
  <artifactId>spring-aop</artifactId>
  <packaging>jar</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>spring-aop Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    
    <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.2.6</version>
        </dependency>
  </dependencies>
  <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值