五.AOP

代理的类型分为两种,一种为静态代理,一种为动态代理。代理的目的是为了在切面上扩展业务,而不用改变原来的功能模块,具有很高的延伸性,但是代码量会增加两倍甚至更多。

1.静态代理

    静态代理如下代码所示:

interface Shopping {
    void buy();
}

class Client implements Shopping {
    public void buy() {
        System.out.println("我想买这件商品");
    }
}

class StaticProxy implements Shopping {
    private Shopping shopping;

    public StaticProxy(Shopping shopping) {
        this.shopping = shopping;
    }

    public void buy() {
        System.out.println("降价促销,疯狂大甩卖了!");
        shopping.buy();
    }
}

public class StaticProxyTest {
    public static void main(String[] args) {
        Client client = new Client();
        StaticProxy service = new StaticProxy(client);
        service.buy();
    }
}

2.动态代理

    动态代理需要通过创建继承了InvocationHandler接口的类,通过使用这个类,来创建代理,该类的代码如下:

package AOP;

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

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 {
		// TODO Auto-generated method stub
		Object result=method.invoke(target, args);
		return result;
	}
     
}

该类使用到了两个特征明显的方法,分别是Proxy.newProxyInstance()和method.invoke().

其中Proxy.newProxyInstance()有三个传递参数,分别为:

1.loader:该类加载器

2.interface:目标类实现的接口

3.invocationHadler:该处理器

关于Invoke方法,相当于省略了静态代理时还要重写的方法,用到了JAVA的反射机制。具体的内容看:

JAVA的Invoke方法_JACKEYLLLLLOVE的博客-CSDN博客

3.SpringAOP的配置文件

在使用AOP之前要引入一个aspectjweaver包,暂时不知道干什么的。

相应地址https://mvnrepository.com/

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">

</beans>

4.SpringAOP的基本信息

相应信息如下:

SpringAOP,通过Advice定义横切逻辑,Spring中支持五种类型的Advice.

 即Aop在不改变原有代码的情况下,去增加新的功能。

5.使用Spring实现AOP

实例类:

package SpringAop;

import org.springframework.stereotype.Component;

@Component
public class UserServiceImp implements UserService{

	@Override
	public void add() {
		// TODO Auto-generated method stub
		System.out.println("添加了一个用户");
	}

	@Override
	public void delete() {
		// TODO Auto-generated method stub
		System.out.println("删除了一个用户");
	}

	@Override
	public void update() {
		// TODO Auto-generated method stub
		System.out.println("更新了信息");
	}

	@Override
	public void select() {
		// TODO Auto-generated method stub
		System.out.println("选择了一个用户");
	}

}

 方式一:使用Spring的接口。

相关日志类代码如下:

package SpringAop;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.stereotype.Component;

@Component
public class Log implements MethodBeforeAdvice{

	@Override
	//method:要执行的目标对象的方法
	//args:参数
	//target:目标对象
	public void before(Method method, Object[] args, Object target) throws Throwable {
		// TODO Auto-generated method stub
		System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了");
	}

}
package SpringAop;
import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;
import org.springframework.stereotype.Component;

@Component
public class AfterLog implements AfterReturningAdvice{

	@Override
	//returnValue:返回值
	public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("执行了"+method.getName()+"方法.返回结果为"+returnValue);
	}

}

配置文件如下:

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">
 
  <!-- 使用注释<context:component-scan base-package="SpringAop"/> -->
    <bean id="log" class="SpringAop.Log"></bean>
    <bean id="afterLog" class="SpringAop.AfterLog"></bean>
    <bean id="userService" class="SpringAop.UserServiceImp"></bean>
     
     <!-- 方式一:使用Spring原生的API -->   
     <!-- 配置AOP -->
    <aop:config>
       <!-- 切入点:expression:表达式;execution():要执行的位置:-->
       <aop:pointcut id="point" expression="execution(* SpringAop.UserServiceImp.*(..))"/>
       <!-- 执行环绕 -->
       <aop:advisor advice-ref="log" pointcut-ref="point"/>
       <aop:advisor advice-ref="afterLog" pointcut-ref="point"/>
    </aop:config>
          

</beans>

方式二:使用自定义类实现切面。

自定义类如下:

package SpringAop;

public class DivPointCut 
{
	public void before()
	{
		System.out.println("----方法执行前----");
	}
	public void after()
	{
		System.out.println("----方法执行后----");
	}

}

Spring配置文件如下:

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">
 
  <!-- 使用注释<context:component-scan base-package="SpringAop"/> -->
    <bean id="log" class="SpringAop.Log"></bean>
    <bean id="afterLog" class="SpringAop.AfterLog"></bean>
    <bean id="userService" class="SpringAop.UserServiceImp"></bean>
     
     <!-- 方式一:使用Spring原生的API -->   
     <!-- 配置AOP -->
    <!-- <aop:config>
       切入点:expression:表达式;execution():要执行的位置:
       <aop:pointcut id="point" expression="execution(* SpringAop.UserServiceImp.*(..))"/>
       执行环绕
       <aop:advisor advice-ref="log" pointcut-ref="point"/>
       <aop:advisor advice-ref="afterLog" pointcut-ref="point"/>
    </aop:config> -->
    
    <!--方法二:自定义类 -->
    <bean id="diy" class="SpringAop.DivPointCut "></bean>
      
    <aop:config>
    <!-- 自定义切面,ref要引用的类 -->
      <aop:aspect ref="diy">
      <aop:pointcut id="point" expression="execution(* SpringAop.UserServiceImp.*(..))"></aop:pointcut>
      <aop:before pointcut-ref="point" method="before()"/>
      <aop:after pointcut-ref="point" method="after()"/>
      </aop:aspect>
    </aop:config>    

</beans>

方式三:使用注解实现AOP

Spring配置文件如下:

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">
 
  <!-- 使用注释<context:component-scan base-package="SpringAop"/> -->
    <bean id="log" class="SpringAop.Log"></bean>
    <bean id="afterLog" class="SpringAop.AfterLog"></bean>
    <bean id="userService" class="SpringAop.UserServiceImp"></bean>
     
     <!-- 方式一:使用Spring原生的API -->   
     <!-- 配置AOP -->
    <!-- <aop:config>
       切入点:expression:表达式;execution():要执行的位置:
       <aop:pointcut id="point" expression="execution(* SpringAop.UserServiceImp.*(..))"/>
       执行环绕
       <aop:advisor advice-ref="log" pointcut-ref="point"/>
       <aop:advisor advice-ref="afterLog" pointcut-ref="point"/>
    </aop:config> -->
    
    <!--方法二:自定义类 -->
    <!-- <bean id="diy" class="SpringAop.DivPointCut "></bean>
      
    <aop:config>
    自定义切面,ref要引用的类
      <aop:aspect ref="diy">
      <aop:pointcut id="point" expression="execution(* SpringAop.UserServiceImp.*(..))"></aop:pointcut>
      <aop:before pointcut-ref="point" method="before()"/>
      <aop:after pointcut-ref="point" method="after()"/>
      </aop:aspect>
    </aop:config>     -->
    
        <!--方法三:自定义类 -->
     <bean id="anotationPointCut" class="SpringAop.AnotationPointCut"></bean>  
     <!-- 开启注释支持 JDK(默认 proxy-target-class="false" cglib("true")) -->
     <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

</beans>

相应的实现代码如下:

package SpringAop;

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

//方式三:使用注解方式实现AOP

@Aspect //标记这个类是一个问题
public class AnotationPointCut 
{
	@Before("execution(* SpringAop.UserServiceImp.*(..))")
	public void before()
	{
		System.out.println("----方法执行前----");
	}
	@After("execution(* SpringAop.UserServiceImp.*(..))")
	public void after()
	{
		System.out.println("----方法执行后----");
	}
	//在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点
	@Around("execution(* SpringAop.UserServiceImp.*(..))")
	public void around(ProceedingJoinPoint jp) throws Throwable
	{
		System.out.println("环绕前");
		System.out.println(jp.getSignature());//获得签名
		//执行方法
		Object proceed=jp.proceed();
		System.out.println("环绕哦后");
	}

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值