其他分享
首页 > 其他分享> > 【跟着狂神学spring】spring系列二aop

【跟着狂神学spring】spring系列二aop

作者:互联网

AOP: Aspect oriented Programming,面向切面变成,通过预编译和运行期间动态代理实现程序功能。在不修改代码情况下,给程序加功能,当然也可以直接用静态代理或者动态代理去做。不过按照spring说法
aop允许分离应用的业务逻辑和系统级服务

主要功能

百度说是:把日志记录、性能统计、安全控制、事务处理、异常处理从业务逻辑代码剥离出来

静态代理方式

代理接口: Rent
真实角色:Host
代理:Proxy

public interface Rent {
    void rent();
}

public class Host implements Rent {
    @Override
    public void rent() {
        System.out.println("真实对象出租房屋");
    }
}

public class Proxy implements Rent{
    private Host host; //代理角色依赖与真实角色
    public Proxy() {
    }
    public Proxy(Host host) {
        this.host = host;
    }
    public void see(){
        System.out.println("带客户看房源");
    }
    @Override
    public void rent() {
        see();
        host.rent();
        contact();
    }
    public void contact() {
        System.out.println("签合同");
    }
}

测试端

public class Client {
    public static void main(String[] args) {
        Host host = new Host();
        Proxy proxy = new Proxy(host);
        proxy.rent();
    }
}

动态代理

不显式生成那个Proxy代理类

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* Proxy和InvocationHandler两个类
*/
public class ProxyInvocationHandler implements InvocationHandler{
    //被代理的接口
    private Object target;

    //注入代理的接口
    public void setTarget(Object target){
        this.target = target;
    }

    //生成得到代理类
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                target.getClass().getInterfaces(), this);
    }
    //处理代理实例,并返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        log(method.getName());
        Object result = method.invoke(target, args);
        return result;
    }
    public void log(String msg ){
        System.out.println("执行 " + msg + "方法");
    }
}

测试端:

public class Client {
    public static void main(String[] args) {
        /**
         * 主要设计InvocationHandler 、 Proxy
         */

        Host host = new Host();//真实代理的角色
        //代理角色  运行时创建
        ProxyInvocationHandler  hander = new ProxyInvocationHandler();
//       //设置代理的对象
        hander.setTarget(host);
        //生成动态代理类
        Rent1 proxy = (Rent1) hander.getProxy();
        proxy.rent();
    }
}

【bug】Rent1与ProxyInvocationHandler在同一个包下,然后尽然说找不到这个Rent1,尚未解决这个问题

AOP

案例
UserSerivice
UserServiceImpl

public interface UserService {
    void add();
    void delete();
    void search();
    void update();
}

public class UserServiceImpl implements UserService{
    public UserServiceImpl() {
    }

    @Override
    public void add() {
        System.out.println("添加一个用户");
    }
    @Override
    public void delete() {
        System.out.println("delete一个用户");
    }
    @Override
    public void search() {
        System.out.println("search一个用户");

    }
    @Override
    public void update() {
        System.out.println("update一个用户");

    }
}

实现AOP三种方式

<?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
            https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--    注册bean-->
    <bean id="userService" class="com.example.demo03.UserServiceImpl" />
    <bean id="log" class="com.example.demo03.Log"/>
    <bean id="afterlog" class="com.example.demo03.AfterLog"/>
<!--    方式一 使用原声的spring api接口-->
<!--    配置aop-->
<!--    <aop:config>-->
<!--&lt;!&ndash;        切入点:expression表达式,execution(要执行的位置!* 报名)&ndash;&gt;-->
<!--        <aop:pointcut id="pointcut" expression="execution(* com.example.demo03.UserServiceImpl.*(..))"/>-->
<!--&lt;!&ndash;        执行环绕增加&ndash;&gt;-->
<!--        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>-->
<!--        <aop:advisor advice-ref="afterlog" pointcut-ref="pointcut"/>-->
<!--    </aop:config>-->

<!--    方式二 使用-->
<!--    <bean id="diy" class="com.example.demo03.DIY"/>-->
<!--    <aop:config>-->
<!--&lt;!&ndash;        自定义切面,ref是要引用的类&ndash;&gt;-->
<!--        <aop:aspect ref="diy">-->
<!--&lt;!&ndash;            切入点&ndash;&gt;-->
<!--            <aop:pointcut id="point" expression="execution(* com.example.demo03.UserServiceImpl.*(..))"/>-->
<!--&lt;!&ndash;            通知&ndash;&gt;-->
<!--            <aop:before method="before" pointcut-ref="point"/>-->
<!--            <aop:after method="after" pointcut-ref="point"/>-->
<!--         </aop:aspect>-->
<!--    </aop:config>-->

<!--    方式三 使用注解方式-->
    <bean id="annotationpointcut" class="com.example.demo03.AnnotationPointCut"/>
<!--    aop:aspectj-autoproxy标签中 有个默认代理类 -->
<!--    开启注解支持  jdk(默认) cglib-->
    <aop:aspectj-autoproxy proxy-target-class="false"/>
</beans>

方式一中用到的Log和AfterLog类

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class Log implements MethodBeforeAdvice {
    /**
     *
     * @param method:要执行的目标对象的方法
     * @param objects: 参数
     * @param o: 目标对象
     * @throws Throwable
     */
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println(o.getClass().getName() + "的"+method.getName() + "被执行了");
    }
}


import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

public class AfterLog implements AfterReturningAdvice {
    /**
     *
     * @param o: 返回的结果
     * @param method
     * @param objects
     * @param o1
     * @throws Throwable
     */
    @Override
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("调用了"+method.getName() + "返回值:" + o);
    }
}

方式二中使用的DIY类

public class DIY{
    public void before(){
        System.out.println("调用了before" );
    }
    public void after(){
        System.out.println("调用了after" );
    }
}

方式三使用到的直接类

package com.example.demo03;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect //表明这个类是一个切面
public class AnnotationPointCut {

    @Before("execution(* com.example.demo03.UserServiceImpl.*(..))")
    public void befor(){
        System.out.println("before");
    }
    @After("execution(* com.example.demo03.UserServiceImpl.*(..))")
    public void after(){
        System.out.println("after");
    }
    @Around("execution(* com.example.demo03.UserServiceImpl.*(..))")
    public void aroud(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("环绕前");
        Signature signature = jp.getSignature();
        System.out.println("signature" + signature);
        Object proceed = jp.proceed(); //执行方法
        System.out.println("环绕后");
    }
}

标签:spring,void,Object,System,aop,println,public,神学,out
来源: https://blog.csdn.net/Alearn_/article/details/120461237