Spring 之 AOP 動態代理實現原理
阿新 • • 發佈:2019-02-19
pom.xml
<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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.et</groupId> <artifactId>SpringAopPrinciple</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.3.9.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.9.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>4.3.9.RELEASE</version> </dependency> <!-- JUnit Java語言的單元測試框架 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- Cglib 提供強大的動態代理 --> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2</version> </dependency> </dependencies> <build> <plugins> <!-- 指定JDK版本和編碼的外掛 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.7</source> <target>1.7</target> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> </build> </project>
package cn.et.dao;
public interface UserDao {
public void addUser();
}
package cn.et.dao.impl;
import cn.et.dao.UserDao;
public class UserDaoImpl implements UserDao {
public void addUser(){
System.out.println("新增使用者");
}
}
package cn.et.dao.impl; public class StudentDao { public void addStudent(){ System.out.println("新增學生"); } }
package cn.et.utils; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class MyInvocationHandler implements InvocationHandler{ private Object targetObj; public MyInvocationHandler(Object targetObj){ this.targetObj = targetObj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("許可權驗證"); Object resultObj = method.invoke(targetObj, args); System.out.println("日誌記錄"); return resultObj; } }
package cn.et.utils;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz){
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
//通過位元組碼技術動態建立子類例項
return enhancer.create();
}
//實現MethodInterceptor介面方法
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("許可權驗證");
Object result = proxy.invokeSuper(obj, args);
System.out.println("日誌記錄");
return result;
}
}
package cn.et.utils;
import java.lang.reflect.Proxy;
import org.junit.Test;
import cn.et.dao.UserDao;
import cn.et.dao.impl.StudentDao;
import cn.et.dao.impl.UserDaoImpl;
public class Checkout {
@Test
public void Testing(){
UserDao userDao = new UserDaoImpl();
/*
Spring AOP(面向切面程式設計),擴充套件功能不修改原始碼實現,採用橫向抽取機制,取代了傳統縱向繼承體系重複性程式碼
橫向抽取機制,底層使用動態代理方式實現
針對有介面的情況時使用JDK中的java.lang.reflect類庫提供的動態代理
針對沒有介面的情況時,使用Cglib框架提供的動態代理
*/
MyInvocationHandler handler = new MyInvocationHandler(userDao);
UserDao proxyUserDao = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(),userDao.getClass().getInterfaces(),handler);
proxyUserDao.addUser();
System.out.println("。。。。。。。。。。。。。");
CglibProxy proxy = new CglibProxy();
StudentDao proxyImp = (StudentDao)proxy.getProxy(StudentDao.class);
proxyImp.addStudent();
}
}