SpringAop的7种实现方式

springAOP的实现方式

1.原生JDK实现

(1)定义1个切面类

package com.springAOP.aop01;
public class MyAspect {
    public void before(){
        System.out.println("this is before");
    }
    public void after(){
        System.out.println("this is after");
    }
}

(2)编写一个代理工厂UserServiceFactory

Proxy的静态方法newProxyInstance()方法,可以实现静态代理

package com.springAOP.aop01;

import com.springAOP.service.IUserService;
import com.springAOP.service.impl.UserServiceImpl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

public class UserServiceFactory {

    public static IUserService getUserService() {
        IUserService service = new UserServiceImpl();
        MyAspect myAspect = new MyAspect();
        /**
         * Proxy的静态方法newProxyInstance()方法,可以实现静态代理
         * 含有三个参数
         *  1.  类加载器, 当前类对象的getClassLoader()
         *  2.  该对象的接口们
         *  3.  调用处理类,回调接口
         */
        IUserService userService = (IUserService) 
            //getClassLoader():取得该Class对象的类装载器
            Proxy.newProxyInstance(UserServiceFactory.class.getClassLoader(), service.getClass().getInterfaces(), new InvocationHandler() {
            /**
             *  调用处理类,回调接口
             *  该回调方法含有三个参数
             * @param proxy 第一个是代理对象
             * @param method  第二个是代理方法对象
             * @param args 第三个是代理方法的参数列表
             * @return
             * @throws Throwable
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//                在主任务前加上辅助功能
                myAspect.before();
//                打印调用的方法名,和参数列表
                System.out.println(method.getName() + "\t" + Arrays.toString(args) + "\t");
//             通过方法名和参数列表 调用  UserServiceImpl下匹配的方法
                Object obj = method.invoke(service, args);
                //                在主任务后加上辅助功能
                myAspect.after();
                return obj;

            }

        });
        return userService;
    }
}

(3)测试运行

public class TestAOP01 {

    @Test
    public void test1(){
        IUserService ius = new UserServiceImpl();
        ius.getAllUsers();
        System.out.println("-----------------");
        ius.getUserByUid(1);
        System.out.println("-----------------");
        ius.getUsersByPage(1, 3);
        System.out.println("-----------------");
        User u = new User();
        ius.saveUser(u);
        System.out.println("-----------------");
        ius.updateUser(u);
        System.out.println("-----------------");
        ius.deleteUser(1);
        System.out.println("-----------------");
    }

    @Test
    public void testAOP01(){
        IUserService ius = UserServiceFactory.getUserService();
        ius.getAllUsers();
        System.out.println("-----------------");
        ius.getUserByUid(1);
        System.out.println("-----------------");
        ius.getUsersByPage(1, 3);
        System.out.println("-----------------");
        User u = new User();
        ius.saveUser(u);
        System.out.println("-----------------");
        ius.updateUser(u);
        System.out.println("-----------------");
        ius.deleteUser(1);
        System.out.println("-----------------");
    }
}

结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KIrSI63o-1665278170688)(springAOP.assets/image-20220920210316272.png)]

可以看出,通过反射来让静态工厂来代理来实现AOP的功能

2.使用Enhancer增强类来实现

//  aop的第二种实现方式,使用Enhancer增强类
public class UserServiceFactory {
    public static IUserService getUserService(){
        //      总共分为四个步骤:
        IUserService ius = new UserServiceImpl();
        //      1.  创建Enhander增强类对象
        Enhancer eh = new Enhancer();
        //      2.  设置增强类对象的superClass,设置当前对象的父接口
        eh.setSuperclass(IUserService.class);
        //      3.  设置增强类对象的回调接口
        //          回调接口包含一个回调方法intercept,
        eh.setCallback(new MethodInterceptor() {
            /**
             * 回调方法,该方法含有四个参数:
             * @param o   1.  代理对象
             * @param method  2.  方法对象
             * @param objects  3.  方法的参数列表
             * @param methodProxy   4.  给每个方法设置了代理
             * @return
             * @throws Throwable
             */
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("this  is before");
                Object obj = method.invoke(ius, objects);
                System.out.println("this  is after");
                return obj;
            }
        });
        //  使用Enhance对象的create()方法创建我们需要的对象,
        //      由于第二步设置了当前对象的superClass,
        IUserService myIUS = (IUserService) eh.create();
        return myIUS;
    }
}

(2.)测试

public class TestAOP02 {
    @Test
    public void testAOP02(){
        IUserService ius = UserServiceFactory.getUserService();
        ius.getAllUsers();
        System.out.println("=============");
        ius.getUserByUid(9);
        System.out.println("=============");
        ius.getUsersByPage(3, 20);
        System.out.println("=============");
        User u = new User();
        ius.saveUser(u);
        System.out.println("=============");
        ius.updateUser(u);
        System.out.println("=============");
        ius.deleteUser(1);
        System.out.println("=============");
    }
}

3.使用ProxyFactoryBean来实现代理

1.定义1个切面类

public class MyAspect implements MethodInterceptor {
    public void before(){
        System.out.println("this is before");
    }
    public void after(){
        System.out.println("this is after");
    }

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        before();
        //  proceed()指的是要处理的业务方法,在之前和之后可以分别添加辅助功能代码
        Object obj = invocation.proceed();
        after();
        return obj;
    }
}

2.配置xml文件

cglib: code generation library:是一个强大的代码生产类库,效率更高

<?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="ius" class="com.springAOP.service.impl.UserServiceImpl" />
    <bean id="ma" class="com.springAOP.aop03.MyAspect" />

    <!--
    使用ProxyFactoryBean来实现代理
        设置了四个属性:
            target:目标,在哪个对象之上实现代理
            interfaces:接口们,如果接口有多个,可以按照集合方式注入
                <list>
                    <value>com.springAOP.service.IUserService</value>
                    <value>com.springAOP.service.IUserService</value>
                    <value>com.springAOP.service.IUserService</value>
                    <value>com.springAOP.service.IUserService</value>
                </list>
            interceptorNames:拦截名称,该名称对应的类要实现一个接口MethodInterceptor,
                实现该接口,必须实现该接口的抽象方法invoke();
            optimize:是否强制使用cglib动态代理
                cglib: code generation library:是一个强大的代码代码生产类库,效率更高
    -->
    <bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="ius" />
        <property name="interfaces" value="com.springAOP.service.IUserService" />
        <property name="interceptorNames" value="ma" />
        <property name="optimize" value="true" />
    </bean>
</beans>

3.测试运行

public class TestAOP03 {

    @Test
    public void testAOP03(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("aop03.xml");

        IUserService ius = ac.getBean("proxy", IUserService.class);

        ius.getAllUsers();
        System.out.println("================");
        ius.getUserByUid(1);
        System.out.println("================");
        ius.getUsersByPage(1, 5);
        System.out.println("================");
        User u = new User();
        System.out.println("================");
        ius.saveUser(u);
        System.out.println("================");
        ius.updateUser(u);
        System.out.println("================");
        ius.deleteUser(1);
    }
}

4.aop:config实现代理

1.切面类

public class MyAspect implements MethodInterceptor {
    public void before(){
        System.out.println("this is before");
    }
    public void after(){
        System.out.println("this is after");
    }
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        before();
        Object obj = invocation.proceed();
        after();
        return obj;
    }
}

2.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" 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="ius" class="com.springAOP.aop04.service.impl.UserServiceImpl" />
    <bean id="ma" class="com.springAOP.aop04.service.MyAspect" />

    <!--
        aop:config实现代理,注意需要添加对象的ns和xsi
            proxy-target-class="true":强制使用cgLib的动态代理
            aop:pointcut: 定义一个切点类
                expression指定了一种统配规则
                    * com.springAOP.aop04.service.*.*(..)
                    返回值  包.接口.方法名(参数列表)
                        expression="execution(boolean com.springAOP.aop04.service.*.*(..))"
                        expression="execution(boolean com.springAOP.aop04.service.*.*(..))"
                        expression="execution(java.util.List com.springAOP.aop04.service.*.*(..))“
                        expression="(execution(java.util.List com.springAOP.aop04.service.*.*(..)) or execution(boolean com.springAOP.aop04.service.*.*(..)))"
    -->
    <aop:config proxy-target-class="true">
        <aop:pointcut id="pt" expression="(execution(java.util.List com.springAOP.aop04.service.*.*(..)) or execution(boolean com.springAOP.aop04.service.*.*(..)))"/>
        <aop:advisor advice-ref="ma" pointcut-ref="pt" />
    </aop:config>
</beans>
  @Test
    public void testAOP04(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("aop04.xml");
        IUserService ius = ac.getBean("ius", IUserService.class);
        ius.getAllUsers();
        System.out.println("================");
        ius.getUserByUid(1);
        System.out.println("================");
        ius.getUsersByPage(1, 5);
        System.out.println("================");
        User u = new User();
        System.out.println("================");
        ius.saveUser(u);
        System.out.println("================");
        ius.updateUser(u);
        System.out.println("================");
        ius.deleteUser(1);
    }

5.JoinPoint加入点

public class MyAspect {

    /**
     * JoinPoint加入点,可以动态获取每一个业务方法中的所有信息
     *  getArgs()方法可以获取业务方法的参数列表
     *  getTarget()方法可以获取被代理对象的信息
     *  toString()可以获取业务方法的具体信息
     * @param jp
     */
    public void before(JoinPoint jp){
        System.out.println(Arrays.toString(jp.getArgs()) + "   " + jp.getTarget() + "     " + jp.toString());
        System.out.println("this is before");
    }

    public void after(){
        System.out.println("this is after");
    }

    public Object around(ProceedingJoinPoint pjp){

        try {

            System.out.println("this is around before");
            Object obj = pjp.proceed();
            System.out.println("this is around after");

            return obj;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }

        return null;
    }

    public void myReturn(Object obj){
        System.out.println("this is my return " + obj);
    }

    public void myThrow(Throwable e){
        System.out.println("this is my throw " + e);
    }
}

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" 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="ius" class="com.springAOP.aop05.service.impl.UserServiceImpl" />
    <bean id="ma" class="com.springAOP.aop05.service.MyAspect" />

    <aop:config proxy-target-class="true">
        <aop:aspect ref="ma">
            <aop:pointcut id="mpt" expression="execution(* com.springAOP.aop05.service.*.*(..))"/>

            <!--
                五种通知方式实现AOP
                    前置通知,在业务方法之前执行辅助功能
                    后置通知,在业务方法之后执行辅助功能
                    环绕通知,分别在业务方法之前和之后执行辅助功能,所对应的业务方法需要一个ProceddingJoinPoint参数
                    带有返回值的通知,可以动态拿到不同业务方法的返回值,需要Object obj对象用来接收每个方法各自的返回值
                    带有异常抛出的通知,可以获取异常信息,需要定义Throwable对象来接收异常对象
            -->
            <aop:before method="before" pointcut-ref="mpt" />
            <aop:after method="after" pointcut-ref="mpt" />
            <aop:around method="around" pointcut-ref="mpt" />
            <aop:after-returning method="myReturn" pointcut-ref="mpt" returning="obj" />
            <aop:after-throwing method="myThrow" pointcut-ref="mpt" throwing="e" />
        </aop:aspect>
    </aop:config>
</beans>

测试

public class TestAOP05 {

    @Test
    public void testAOP05(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("aop05.xml");

        IUserService ius = ac.getBean("ius", IUserService.class);

        ius.getAllUsers();
        System.out.println("================");
        ius.getUserByUid(1);
        System.out.println("================");
        ius.getUsersByPage(1, 5);
        System.out.println("================");
        User u = new User();
        System.out.println("================");
        ius.saveUser(u);
        System.out.println("================");
        ius.updateUser(u);
        System.out.println("================");
        ius.deleteUser(1);
    }
}

6.注解方式

@Component//声明这是一个组件
@Aspect//声明这是一个切面类
public class MyAspect {

    @Pointcut(value = "execution(* com.springAOP.aop06.service.*.*(..))")
    public void all(){}

    /**
     * JoinPoint加入点,可以动态获取每一个业务方法中的所有信息
     *  getArgs()方法可以获取业务方法的参数列表
     *  getTarget()方法可以获取被代理对象的信息
     *  toString()可以获取业务方法的具体信息
     * @param jp
     */
    @Before("all()")
    public void before(JoinPoint jp){
        System.out.println(Arrays.toString(jp.getArgs()) + "   " + jp.getTarget() + "     " + jp.toString());
        System.out.println("this is before");
    }

    @After("all()")
    public void after(){
        System.out.println("this is after");
    }

    @Around("all()")
    public Object around(ProceedingJoinPoint pjp){

        try {

            System.out.println("this is around before");
            Object obj = pjp.proceed();
            System.out.println("this is around after");

            return obj;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }

        return null;
    }

    @AfterReturning(value = "all()", returning = "obj")
    public void myReturn(Object obj){
        System.out.println("this is my return " + obj);
    }

    @AfterThrowing(value = "all()", throwing = "e")
    public void myThrow(Throwable e){
        System.out.println("this is my throw " + e);
    }
}

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"
       xmlns:context="http://www.springframework.org/schema/context"
       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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--
        context:component-scan: 上下文的组件扫描
            base-package,指定哪个包下的所有组件都将被扫描到Spring容器中
            想要被扫描到容器中,必须给类添加@Component注解
    -->
    <context:component-scan base-package="com.springAOP.aop06.service" />

    <!--
        aop:aspectj-autoproxy:切面的自动代理
    -->
    <aop:aspectj-autoproxy />
</beans>

测试

public class TestAOP06 {

    @Test
    public void testAOP06(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("aop06.xml");

        IUserService ius = ac.getBean("us", IUserService.class);

        ius.getAllUsers();
        System.out.println("================");
        ius.getUserByUid(1);
        System.out.println("================");
        ius.getUsersByPage(1, 5);
        System.out.println("================");
        User u = new User();
        System.out.println("================");
        ius.saveUser(u);
        System.out.println("================");
        ius.updateUser(u);
        System.out.println("================");
        ius.deleteUser(1);
    }
}

7.实现BeanPostProcessor接口

1.切面类

public class MyAspect {
    public void before(){
        System.out.println("this is before");
    }
    public void after(){
        System.out.println("this is after");
    }
}

2.新增一个类MyBeanPostProcessor实现BeanPostProcessor接口

/**
 * 新增一个类MyBeanPostProcessor实现BeanPostProcessor接口
 *  需要重写两个方法postProcessAfterInitialization和postProcessBeforeInitialization
 *      这两个方法中的参数bean对应的是spring容器中任何业务对象
 */
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("this is postProcessAfterInitialization");

        MyAspect ma = new MyAspect();

        return Proxy.newProxyInstance(MyBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                        ma.before();

                        Object obj = method.invoke(bean, args);

                        ma.after();

                        return obj;
                    }
                });
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("this is postProcessBeforeInitialization");
        return bean;
    }
}

测试

public class TestAOP07 {

    @Test
    public void testAOP07(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("aop07.xml");

        IUserService ius = ac.getBean("ius", IUserService.class);

        ius.getAllUsers();
        System.out.println("================");
        ius.getUserByUid(1);
        System.out.println("================");
        ius.getUsersByPage(1, 5);
        System.out.println("================");
        User u = new User();
        System.out.println("================");
        ius.saveUser(u);
        System.out.println("================");
        ius.updateUser(u);
        System.out.println("================");
        ius.deleteUser(1);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值