Spring框架(四)

版权声明:@Wrial https://blog.csdn.net/qq_42605968/article/details/86694900

在前几次主要写了一些Ioc的配置和实现,这次就到了AOP(面向切面编程),说到AOP还得提一提OOP(面向对象编程)


OOP:核心思想是将客观存在的不同事物抽象成相互独立的类,然后把与事物相关的属性和行为封装到类里,并通过继承和多态来定义类彼此间的关系,最后通过操作类的实例来完成实际业务逻辑的功能需求。**OOP通过继承和多态会使程序之间的耦合度增高,不利于扩展程序。**
AOP:AOP可以对业务逻辑的各个部分进行隔离,**从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率**。主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等。AOP是OOP的一个扩展,用来解决OOP存在的一些缺陷。
OOP与AOP的区别:

1、面向目标不同:简单来说OOP是面向名词领域,AOP面向动词领域。

2、思想结构不同:OOP是纵向结构,AOP是横向结构(由AOP联盟组织提出)。

3、注重方面不同:OOP注重业务逻辑单元的划分,AOP偏重业务处理过程的某个步骤或阶段。


在简单的分析完AOP后,我们开始进入正题,为什么AOP使程序的耦合度降低扩展性增强了呢?因为AOP的实现原理就是采用的动态代理,它既保证了程序的各部分隔离有保证了功能的实现。

在SpringAOP中所实现的动态代理可以从类别上分为两种
一,基于JDK的动态代理(只能对实现接口的类产生代理)
利用JDK创建代理对象,然后实现代理,以前写过利用JDK动态代理的实例(利用动态代理实现字符集编码的自动调整),这种就不在这里举例子了,附上博客链接:https://blog.csdn.net/qq_42605968/article/details/86566681
二,基于Cglib实现的动态代理(用来补充JDK)
Cglib也可以在没有实现的类中产生代理
代码和解析如下
内部类实现:用匿名内部类实现

   public PersonDao CreateProxy() {

//        创建cglib核心类对象
        Enhancer enhancer = new Enhancer();
//        设置父类
        enhancer.setSuperclass(PersonDao.class);
//         回调类似于invocation
//        enhancer.setCallback(this);
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                if ("tellName".equals(method.getName())) {
                    System.out.println("实现代理,已进行增强");
                    return methodProxy.invokeSuper(o, objects);
                }

                return methodProxy.invokeSuper(o, objects);
            }
        });
        PersonDao personDao = (PersonDao) enhancer.create();
        return personDao;
    }

接口实现:实现MethodInterceptor接口

package CglibTest;

        import org.springframework.cglib.proxy.Enhancer;
        import org.springframework.cglib.proxy.MethodInterceptor;
        import org.springframework.cglib.proxy.MethodProxy;

        import java.lang.reflect.Method;

public class cglib implements MethodInterceptor {
    public PersonDao CreateProxy() {

//        创建cglib核心类对象
        Enhancer enhancer = new Enhancer();
//        设置父类
        enhancer.setSuperclass(PersonDao.class);
//         回调类似于invocation
        enhancer.setCallback(this);
//        enhancer.setCallback(new MethodInterceptor() {
//            @Override
//            public Object intercept(Object proxy, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        PersonDao personDao = (PersonDao) enhancer.create();
        return personDao;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        if ("tellName".equals(method.getName())) {
            System.out.println("实现代理,已进行增强");
            return methodProxy.invokeSuper(o, objects);
        }
        return methodProxy.invokeSuper(o, objects);
    }
}

测试类:

  @Test
    public void test(){
     PersonDao personDao1 = new cglib().CreateProxy();
     personDao1.tellName();
    }

在这里插入图片描述
当然我这里也只是简单的介绍和使用,只是为了更好的了解AOP。

AOP入门

入门当然要熟悉AOP的一些术语了,我罗列了一些AOP术语在我的另一篇博客上,附上链接:https://blog.csdn.net/qq_42605968/article/details/86695041
熟悉了术语之后,那就用一个小例子来了解一下这些术语的用法,轻轻松松的入门。
1.建立如下的测试包结构并导入AspectJ的jar包,因为Spring中采用的AspectJ的开源框架,它做的AOP比Spring更易于使用。
在这里插入图片描述
2.实现测试结构

package AOP;

public interface PersonDao1 {
    public void tellName();
    public void tellAge();
}
package AOP;

public class PersonDaoimpl implements PersonDao1 {
    @Override
    public void tellName() {
        System.out.println("tellName");
    }

    @Override
    public void tellAge() {
        System.out.println("tellAge");
    }
}

package AOP;

public class MyAspect {
    public void Inform(){
        System.out.println("before infrormation");
    }
}

package AOP;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;

//Spring工厂和JUnit结合,省去了创建工厂的过程,测试更加方便
@RunWith(SpringJUnit4ClassRunner.class)
//配置xml
@ContextConfiguration("classpath:AOPCof.xml")
public class Test01 {
    @Resource(name = "PersonDao1")
    private PersonDao1 personDao;
    @Test
    public void test01(){
        personDao.tellAge();
        personDao.tellName();
    }
}

xml配置,使用aop就要把aop加载进来,在设置切点时expression必须用execution表达式,切点配置 *代表任意返回值,…代表任意参数
实现步骤
1.先配置需要配置的bean
2.配置切点,需要把那个包下的那个方法设置为切点
3.配置切面,切面是多个通知多个切入点的组合,可以选择通知的前后给切点设置通知

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

    <bean id="PersonDao1" class="AOP.PersonDaoimpl"></bean>
    <bean id="MyAspect" class="AOP.MyAspect"></bean>
    <aop:config>
        <!--切点配置 *代表任意返回值,..代表任意参数-->
        <aop:pointcut id="pointcut01" expression="execution(* AOP.PersonDaoimpl.tellName(..))" ></aop:pointcut>
        <!--切面配置-->
        <aop:aspect ref="MyAspect">
            <aop:before method="Inform" pointcut-ref="pointcut01"></aop:before>
        </aop:aspect>
    </aop:config>
</beans>

给tellName之前设置的通知
在这里插入图片描述
这就是AOP的入门小案例的完整实现。
下一篇就细讲AOP的一些学问!







猜你喜欢

转载自blog.csdn.net/qq_42605968/article/details/86694900