面向切面编程时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>