AOP
1). AOP: AOP Aspect Oriented Programing 面向切面编程
2).AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码
3). Spring AOP使用纯Java实现,不需要专门的编译过程和类加载器,在运行
期通过代理方式向目标类织入增强代
正常使用类:*.java -> javac -> .class -> java -> 加载该class到虚拟机
动态代理 直接生成了.class字节码, 加载该class到虚拟机
AOP的好处
为什么说 AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码呢?
为什么spring要采用aop横向抽取机制?
因为传统的纵向继承方式,是采用继承的方式来利用这些重复的代码。这样做会增加类与类的耦合性,程序会显得特别笨重,而且后期也难以维护。
而aop采用的横向抽取机制则避免了这一问题。
AOP底层原理;
AOP的这种横向抽取机制就是采用了代理机制。
spring默认使用jdk动态代理,如果没有实现接口,就使用cglib代理
1)JDK动态代理:只能针对接口实现代理, jdk动态代理在高版本中性能优于CGLib
//目标类和代理类实现的 接口
public interface UserDao {
public void insert();
public void delete();
public void update();
public void select();
}
//目标类
public class UserDaoTarget implements UserDao {
public void insert() {
System.out.println("插入方法");
}
public void delete() {
System.out.println("删除方法");
}
public void update() {
System.out.println("更新方法");
}
public void select() {
System.out.println("查询方法");
}
}
//代理类
public class ProxyUserDao {
private UserDao userDao;
public ProxyUserDao(UserDao userDao) {
this.userDao = userDao;
}
public UserDao createProxy(){
//获得类加载器
ClassLoader classLoader = userDao.getClass().getClassLoader();
//代理对象需要实现的接口
Class<?>[] interfaces = userDao.getClass().getInterfaces();
//通知类
UserDaoAdvice userDaoAdvice = new UserDaoAdvice();
UserDao proxy = (UserDao) Proxy.newProxyInstance(classLoader,interfaces,userDaoAdvice);
return proxy;
}
}
//通知类
public class UserDaoAdvice implements InvocationHandler {
UserDao userDao = new UserDaoTarget();
//调用目标对象中的任意方法都相当于调用该invoke方法。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("方法被执行,记录日志信息");
Object obj = method.invoke(userDao,args);
return obj;
}
}
//测试类
public class ProxyTest {
@Test
public void test() {
UserDao userdao = new UserDaoTarget();
//获得代理对象
UserDao proxy = new ProxyUserDao(userdao).createProxy();
//代理对象调用方法
proxy.delete();
}
}
2).CGLib动态代理:既可以针对接口实现代理,也可以生成子类充当目标父类的代理
//目标类
public class ProductDao {
public void select() {
System.out.println("查询商品");
}
public void insert(){
System.out.println("插入商品");
}
public void update(){
System.out.println("更新商品");
}
public void delete(){
System.out.println("删除商品");
}
}
//代理类
public class CGLibProxy {
private ProductDao productDao;
public CGLibProxy(ProductDao productDao) {
this.productDao = productDao;
}
public ProductDao createproxy(){
//创建核心类
Enhancer enhancer = new Enhancer();
//为其设置父类
enhancer.setSuperclass(productDao.getClass());
//设置回调
enhancer.setCallback(new ProductDaoAdvice());
//创建代理
return (ProductDao) enhancer.create();
}
}
//通知类
public class ProductDaoAdvice implements MethodInterceptor {
ProductDao productDao = new ProductDao();
/*
方法参数说明:Object o 目标对象
Method method 方法对象
Object[] objects 方法中的参数
MethodProxy methodProxy
*/
public Object intercept(Object proxy, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("执行了方法,记录了日志信息");
Object o1 = method.invoke(productDao);
// CGLib特有的方式 :Object o = methodProxy.invokeSuper(proxy);
return o1;
}
}
测试类
public class CGLibTest {
ProductDao productDao = new ProductDao();
@Test
public void test2(){
ProductDao createproxy = new CGLibProxy(productDao).createproxy();
createproxy.delete();
}
}