Note/大学笔记/Java/JAVA EE/Web程序设计笔记06——第三章:从Spring的角度去实现代理.md
2024-01-12 16:35:29 +08:00

6.1 KiB
Raw Blame History

第三章

1.代理

生活中的代理: 代购

从Java的角度去实现代理

3.2.1 JDK动态代理

被代理对象:实现了接口的类 写的就是核心的业务功能

切面类:写的是非核心的业务功能

生成代理对象的类JdkProxy

代码实现同上节课

3.2.2 CGLIB代理

被代理对象:某个类

切面类:

生成代理对象的类CglibProxy

代码实现同上节课

AOP 术语:

AOP面向切面编程

切面类MyAspect

连接点: addUser() deleteUser() 调用前或后

切入点:就是连接点

增强处理/通知:就是切面中的方法 check_permission() log()

目标对象: 被代理对象

代理:代理对象

织入:生成代理对象的过程

从Spring的角度去实现代理

(1)导包: 5个核心包commons-logging spring-context spring-beans spring-core spring-expression 2个包spring-aop aoplliance (2)创建接口和实现类 (3)创建切面类 (4)生成代理对象 xml文件 (5)测试

pom.xml文件

<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>4.3.6.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>aopalliance</groupId>
      <artifactId>aopalliance</artifactId>
      <version>1.0</version>
    </dependency>
package com.aop;

public interface UserDao {
    void addUser();
    void deleteUser();
}
package com.aop;

public class UserDaoImpl implements UserDao {
    @Override
    public void addUser() {
        System.out.println("添加用户");
    }

    @Override
    public void deleteUser() {
        System.out.println("删除用户");
    }
}
package com.aop;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class MyAspect implements MethodInterceptor {
    void check_permission() {
        System.out.println("模拟权限检查");
    }

    void log() {
        System.out.println("模拟记录日志");
    }

    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        check_permission();
        Object proceed = methodInvocation.proceed();//调用目标方法
        log();
        return proceed;
    }
}
<?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">

    <!--    1.目标对象被代理对象-->
    <bean id="userDao" class="com.aop.UserDaoImpl"/>
    <!--    2.切面类对象-->
    <bean id="myAspect" class="com.aop.MyAspect"/>
    <!--    3.生成代理对象-->
    <bean id="userDaoproxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!--        3.1指定代理实现的接口-->
        <property name="proxyInterfaces" value="com.aop.UserDao"/>
        <!--        3.2指定目标对象-->
        <property name="target" ref="userDao"/>
        <!--        3.3指定切面,植入环绕通知-->
        <property name="interceptorNames" value="myAspect"/>
        <!--        3.4指定代理方式true使用cglibfalse默认使用jdk动态代理-->
        <property name="proxyTargetClass" value="false"/>
    </bean>
</beans>
package com.aop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AopTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext =
                new ClassPathXmlApplicationContext("a.xml");
        //被代理对象
        UserDao userDao = (UserDao) applicationContext.getBean("userDao");
        userDao.addUser();
        System.out.println("------------------------------");
        //代理对象
        UserDao userDaoproxy = (UserDao) applicationContext.getBean("userDaoproxy");
        userDaoproxy.addUser();

    }
}

代码实现截图:

image-20220324140614514

不管是从Java角度还是Spring角度实现的代理有一个共同点缺点

代理对象不管调用哪个目标方法,都会切入切面类中的方法。

有没有一种手段,可以让代理对象自由地决定调用哪个目标方法时才切入切面类中的方法?

Aspectj框架实现代理

补充:异常

1.异常类

1算术异常

java.lang.ArithmeticException: / by zero

package com.exception;

public class ExceptionTest {
    static int divide(int x,int y){
        int result=x/y;
        return result;
    }

    public static void main(String[] args){
        int divide = divide(4,0);
        System.out.println(divide);
    }
}

image-20220324142225871

2空指针异常

java.lang.NullPointerException

package com.exception;
class A{
    void a(){}
}
public class ExceptionTest2 {
    static A a;

    public static void main(String[] args){
        a.a();
    }
}

image-20220324143554018

2.处理异常

1捕获异常

try{}catch(){}finally{} finally可以省略catch可以有多个

package com.exception;

public class ExceptionTest5 {
    static int divide(int x,int y) throws Exception{
        int result=x/y;
        return result;
    }

    public static void main(String[] args) {
        try {
            divide(4,0);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2抛异常

throws 当调用了方法抛出异常的方法时,调用者可以继续抛异常,也可捕获异常

package com.exception;

public class ExceptionTest4 {
    static int divide(int x,int y) throws Exception{
        int result=x/y;
        return result;
    }

    public static void main(String[] args) throws Exception {
        divide(4,0);
    }
}