Spring-AOP 面向切面(基础用法)

ps:spring-aop 都是与aspectJ(第三方的jar包,spring提供支持)一起使用,本文只是单纯的了解spring架构是怎么切面的

AOP 分为:

         1.静态代理:使用AOP框架提供的命令进行编译,从而在编译阶段就可以生成AOP代理类,因此也称为编译时增强;静态代理一Aspectj为代表。

         2.动态代理:在运行时借助于JDK动态代理,CGLIB等在内存中临时生成AOP动态代理类,因此也被称为运行时增强,Spring AOP用的就是动态代理。

Spring框架中用到就是JDK动态代理(有接口)或者是CGLIB代理(无接口)。

JDK动态代理

用的是JDK 自带的 java.lang.reflect.InvocationHandler

1、首先创建业务类

public interface UserDao {

    public void select();

    public void deleted();

}

public class UserDaoImpl implements UserDao {
    @Override
    public void select() {
        System.out.println("查找User");
    }

    @Override
    public void deleted() {
        System.out.println("删除User");
    }
}

2、创建代理类

// JDK 的动态代理
public class MyJdkProxy implements InvocationHandler {

    private Object object;

    public MyJdkProxy(Object object) {
        this.object = object;
    }
    // 获得代理类
    public Object createProxy( ){
        // newProxyInstance(类加载器,类的接口,要执行的invoke方法)
        Object proxy = Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this);
        return proxy;
    }

    // 具体的代理业务逻辑 写在这里
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if("select".equalsIgnoreCase(method.getName())){
            System.out.println("-----代理-----");
        }
        return method.invoke(object,args);
    }

}

3、application.xml 配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="userDao" class="com.aop.demo1.UserDaoImpl"/>

</beans>

4、测试类

@RunWith(SpringJUnit4ClassRunner.class) // 让测试运行于Spring测试环境
@ContextConfiguration(locations = {"classpath:applicationContext.xml"}) // 加载 applicationContext.xml配置文件
public class SpringAopDemo1 {

    @Resource(name = "userDao")
    private UserDao userDao;

    @Test
    public void test1() {
        UserDao userDao = new UserDaoImpl();
        MyJdkProxy myJdkProxy = new MyJdkProxy(userDao);
        //获得代理的类
        UserDao proxy = (UserDao) myJdkProxy.createProxy();
        proxy.deleted();
        proxy.select();
    }

}

输出结果:

具体流程:

1、将要被代理的类以参数的形式,放入代理工厂类里面

2、然后调用代理工厂的createProxy(Object obj)创建UserDaoImpl类的代理类,在该方法内,调用Proxy.createProxy()方法创建代理对象。第一个参数是目标对象的类加载器,第二个参数是目标对象实现的接口,第三个参数传入一个InvocationHandler实例,该参数和回调有关系。

3、每当调用目标对象的方法的时候,就会回调该InvocationHandler实例的方法,也就是public Object invoke()方法,我们就可以把限制的条件放在这里,条件符合的时候,就可以调用method.invoke()方法真正的调用目标对象的方法,否则,则可以在这里过滤掉不符合条件的调用。

 

CGLIB代理

使用CGlib的方法和使用Proxy的方法差不多,只是Proxy创建出来的代理对象和目标对象都实现了同一个接口。而CGlib的方法则是直接继承了目标对象

1、引入jar包   我的版本是: 4.3.9.RELEASE

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>${spring.version}</version>
    </dependency>

2、创建业务类

public class StudentDao {

    public void insert() {System.out.println("CGlib-I----插入学生---");}

    public void delete() {
        System.out.println("CGlib-D----删除学生---");
    }

}

3、创建代理类

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
// cglib 动态代理
public class MyCglibProxy implements MethodInterceptor {

    private Object object;

    public MyCglibProxy(Object object) {
        this.object = object;
    }

    // cglib创建代理
    public Object createProxy(){
        // 1、创建核心类
        Enhancer enhancer = new Enhancer();
        // 2、设置父类
        enhancer.setSuperclass(object.getClass());
        // 3、设置回调
        enhancer.setCallback(this);
        // 4、生产代理
        Object proxy = enhancer.create();

        return proxy;
    }


    // 这里写业务逻辑
    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        if("insert".equalsIgnoreCase(method.getName())){
            System.out.println("--这是插入的方法啦啦啦----");
        }
        return methodProxy.invokeSuper(proxy,args);
    }

}

4、application.xml 配置  同上一个applicationContext一样 只是新增

    <bean id="studentDao" class="com.aop.demo2.StudentDao"/>

5、测试类

@RunWith(SpringJUnit4ClassRunner.class) // 让测试运行于Spring测试环境
@ContextConfiguration(locations = {"classpath:applicationContext.xml"}) // 加载 applicationContext.xml配置文件
public class SpringAopDemo2 {

    @Resource(name = "studentDao")
    private StudentDao studentDao;

    @Test
    public void test1() {
        StudentDao studentDao = new StudentDao();
        MyCglibProxy myCglibProxy = new MyCglibProxy(studentDao);
        //获得代理的类
        StudentDao proxy = (StudentDao) myCglibProxy.createProxy();
        proxy.delete();
        proxy.insert();
    }

}

输出结果:

具体流程:

1、将要被代理的类以参数的形式,放入代理工厂类里面

2、然后调用代理工厂的createProxy()创建StudentDao类的代理类,在这一步中,我们使用一个Enhancer类来创建代理对象,不再使用Proxy。使用Enhancer类,需要为其实例指定一个父类,也就是我们 的目标对象。这样,我们新创建出来的对象就是目标对象的子类,有目标对象的一样。除此之外,还要指定一个回调函数,这个函数就和Proxy的 invoke()类似。

 

总结

Spring中AOP代理由Spring的IOC容器负责生成、管理,其依赖关系也由IOC容器负责管理。因此,AOP代理可以直接使用容器中的其它bean实例作为目标,这种关系可由IOC容器的依赖注入提供。Spring创建代理的规则为:

1、默认使用Java动态代理来创建AOP代理,这样就可以为任何接口实例创建代理了

2、当需要代理的类不是代理接口的时候,Spring会切换为使用CGLIB代理,也可强制使用CGLIB

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值