????wei_shuo的个人主页
????wei_shuo的学习社区
????Hello World !

文章目录
Sping AOP代理模式静态代理动态代理
AOP概述Spring实现AOP方式一:使用Spring的API接口实现AOP方式二:自定义实现AOP方式三:使用注解实现AOP

Sping AOP

Spring AOP:控制反转
AOP面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率

代理模式

代理模式是程序设计中的一种设计模式所谓的代理者是指一个类别可以作为其它东西的接口。代理者可以作任何东西的接口:网上连接、存储器中的大对象、文件或其它昂贵或无法复制的资源

代理模式分类:
静态代理动态代理
优势:
真实角色更加纯粹,不用关注公共业务公共业务交给代理角色,实现业务分工公共业务发生扩展时,方便集中管理
劣势:
一个真实角色会产生一个代理,代码量会翻倍、效率降低

静态代理

角色分析:
抽象角色:一般会使用接口或者抽象类来解决真实代理:被代理的角色代理角色:代理真实角色客户:访问代理对象者

接口
public interface Rent {
public void rent();
}
123
真实角色
public class Host {
public void rent(){
System.out.println(“房东房子出租”);
}
}
12345
代理角色
public class Proxy implements Rent{
private Host host;

public Proxy() {
}

public Proxy(Host host) {
this.host = host;
}

public void rent(){
host.rent();
}

//看房
public void seeHouse(){
System.out.println(“中介带你看房”);
}

//收中介费
public void money(){
System.out.println(“收中介费”);
}
}
123456789101112131415161718192021222324
客户端访问代理角色
public class Client {
public static void main(String[] args) {
//创建房东对象
Host host = new Host();
//代理
Proxy proxy = new Proxy(host); //通过代理调用房东对象
proxy.rent();

}
}
12345678910

动态代理

动态代理:
动态代理和静态代理角色一样动态代理的代理类是动态生成动态代理是一个接口,对应一类业务动态代理可以代理多个类,只要实现一个接口
动态代理分类:
基于接口——JDK动态代理基于类——cglibJava字节码——Javasist
两种类了解:
Proxy——代理InvocationHandl——调用处理程序

Proxy类:生成动态代理实例
Proxy创建动态代理类的实例提供了静态方法,也是所有动态代理类的父类的方法创建
方法:
//返回指定的代理实例的调用处理程序
getInvocationHandler(Object proxy)

//返回 java.lang.Class对象的代理类,给出了类装载器和一个阵列的接口
getProxyClass(ClassLoader loader, 类… interfaces)

//如果指定的类是动态生成的可利用 getProxyClass法或代理类 newProxyInstance方法返回true
isProxyClass(类 cl)

//返回指定的接口,将方法调用指定的调用处理程序的代理类的一个实例。
newProxyInstance(ClassLoader loader, 类[] interfaces, InvocationHandler h)
1234567891011

InvocationHandl类:调用处理程序并返回结果
InvocationHandler是通过一个代理实例调用处理程序实现的接口。每个代理实例都有一个相关的调用处理程序。当一个方法是在一个代理实例调用,调用的方法进行编码并派遣其调用处理程序的invoke方法
方法:
//在代理实例上处理方法调用,并返回结果
invoke(Object proxy, 方法 method, Object[] args)
12
proxy — 调用该方法的代理实例method — 反射获取到的接口的方法args — 使用此方法时传入的参数数组

ProxyInvocationHandler动态代理类
public class ProxyInvocationHandl implements InvocationHandler {

//被代理的接口
private Object target;

public void setTarget(Object target) {
this.target = target;
}

//生成得到代理类
public Object getProxy() {
//this.getClass().getClassLoader() 加载类所在位置
//rent.getClass().getInterfaces() 表示代理接口
//this == InvocationHandler实现类
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 + “方法”);
}
}
1234567891011121314151617181920212223242526272829303132
Client客户类
public class Client {
public static void main(String[] args) {
//真实角色:被代理的角色
UserServiceImp userService = new UserServiceImp();
//代理角色:代理真实角色
ProxyInvocationHandl pih = new ProxyInvocationHandl();

//设置代理对象
pih.setTarget(userService);
//动态生成代理类
UserService proxy = (UserService) pih.getProxy();

proxy.query();
}
}

/*
执行了query方法
[Debug]使用了query方法
查询用户
*/
123456789101112131415161718192021

AOP概述

提供声明式事物,允许用户自定义切面

横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是很切关注点,如:日志,安全,缓存,事物……切面(ASPECT):横切关注点被模块化的特殊对象。通知(Advice):切面必须要完成的工作。目标(Target):被通知对象。代理(Proxy):向目标对象应用通知之后创建的对象。切入点(PointCut):切面通知执行的”地点”的定义。连接点(JoinPoint):与切入点匹配的执行点。

Spring实现AOP
方式一:使用Spring的API接口实现AOP

使用AOP织入,需要导入一个依赖包


org.aspectj
aspectjweaver
1.9.4


1234567
applicationContext.xml



12345678910111213

前置Log日志类
public class log implements MethodBeforeAdvice {

//method:要执行的目标对象方法
//object:参数
//target:目标对象
@Override
public void before(Method method, Object[] objects, Object target) throws Throwable {
System.out.println(target.getClass().getName()+”的”+method.getName()+”被执行了”);
}
}
12345678910
后置AfterLog类
public class AfterLog implements AfterReturningAdvice {

//returnValue:返回值
@Override
public void afterReturning(Object returnValue, Method method, Object[] objects, Object o1) throws Throwable {
System.out.println(“执行了”+method.getName()+”放回结果为:”+returnValue);
}
}
12345678
UserService接口
public interface UserService {
public void add();
public void delete();
public void update();
public void select();
}
123456
UserServiceImpl接口实现类
public class UserServiceImpl implements UserService{
public void add() {
System.out.println(“增加了一个用户”);
}

public void delete() {
System.out.println(“删除了一个用户”);
}

public void update() {
System.out.println(“更新了一个用户”);
}

public void select() {
System.out.println(“查询了一个用户”);
}
}
1234567891011121314151617
将UserServiceImpl接口实现类注册到Spring中,即applicationContext.xml中









1234567891011121314151617181920212223242526272829303132333435363738
MyTest测试类
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(“applicationContext.xml”);
//动态代理的是接口
UserService userService = (UserService) context.getBean(“userService”);
userService.delete();

}
}

/*
执行结果:
com.wei.service.UserServiceImpl的delete被执行了
删除了一个用户
执行了delete放回结果为:null
*/
12345678910111213141516

方式二:自定义实现AOP

自定义Diy类
public class DiyPointCut {
public void before(){
System.out.println(“===========方法执行前===========”);
}

public void after(){
System.out.println(“===========方法执行后===========”);
}
}
123456789
将Diy类注册到Spring中,即applicationContext.xml中












12345678910111213141516171819
MyTest测试类
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(“applicationContext.xml”);
//动态代理的是接口
UserService userService = (UserService) context.getBean(“userService”);
userService.delete();

}
}

/*
===========方法执行前===========
删除了一个用户
===========方法执行后===========
*/
123456789101112131415

aop中execution 表达式(*execution(\* 包名.\*.*(..))*)
1
整个表达式可以分为五个部分:
execution(): 表达式主体第一个*号:方法返回类型, *号表示所有的类型包名:表示需要拦截的包名第二个*号:表示类名,*号表示所有的类*(…):最后这个星号表示方法名,*号表示所有的方法,后面( )里面表示方法的参数,两个句点表示任何参数



123

方式三:使用注解实现AOP

创建AnnotationPointCut类
//方式三:使用注解实现AOP
// @Aspect 标注这个类是一个切面
@Aspect
public class AnnotationPointCut {

//后置增强
@Before(“execution(* com.wei.service.UserServiceImpl.*(..))”)
public void before() {
System.out.println(“======方法执行前======”);
}

//前置增强
@After(“execution(* com.wei.service.UserServiceImpl.*(..))”)
public void after() {
System.out.println(“======方法执行后======”);
}

//在环绕增强中,可以给一个参数,代表要获取处理切入的点
@Around(“execution(* com.wei.service.UserServiceImpl.*(..))”)
public void around(ProceedingJoinPoint jp) throws Throwable {
System.out.println(“======环绕前======”);

//执行方法
Object proceed = jp.proceed();

System.out.println(“======环绕后======”);

}
}
123456789101112131415161718192021222324252627282930
将AnnotationPointCut类注册到Spring中,即applicationContext.xml中




12345678
MyTest测试类
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(“applicationContext.xml”);
//动态代理的是接口
UserService userService = (UserService) context.getBean(“userService”);
userService.delete();

}
}

/*
执行结果:
======环绕前======
======方法执行前======
删除了一个用户
======环绕后======
======方法执行后======
*/
123456789101112131415161718

???? 结语:创作不易,如果觉得博主的文章赏心悦目,还请——点赞????收藏⭐️评论????冲冲冲????

文章知识点与官方知识档案匹配,可进一步学习相关知识Java技能树首页概览80657 人正在系统学习中