前言

OOP(Object Oriented Programing)面向对象编程

以对象为根本单位进行程序开发,通过对象间的彼此协同,互相协调,实现程序的构建

POP(Producer Oriented Programing)面向过程(办法,函数)编程

以过程为根本单位的程序开发,通过彼此间协同,互相调用,实现程序的构建

动态代理存在的问题

//实现雷同的接口public class UserServiceProxy implements UserService {    //创立原始对象    private UserServiceImpl userService = new UserServiceImpl();    public void register(User user) {        //实现额定性能        System.out.println("-------------------");        userService.register(user);    }    public boolean login(String name, String password) {        System.out.println("____________________");        return userService.login(name,password);    }}

每一个原始类都会手工编写一个代理类

  • 动态类文件数目过多,不利于项目管理
  • 代码可维护性差

概述

上图展现了一个被划分的典型利用,每个模块的外围性能都是为特定业务畛域提供服务,然而这些模块都须要相似的辅助性能,例如平安和事务管理。

如果要重用通用性能的话,最常见的面向对象技术是继承或者委托。然而,如果在整个利用中都应用雷同的基类,继承往往会导致一个软弱的对象体系,而应用委托可能须要对委托对象进行简单的调用。

切面提供了取代继承和委托的另一种可选计划,而且在很多场景下更清晰简洁,在应用面向切面编程时,咱们依然在一个中央定义通用性能,然而能够通过申明的形式定义这个性能要以何种形式在何处利用,而无需批改受影响的类,横切关注点模块化为非凡的类,这些类被称为切面(aspect)。这样做有两个益处:首先,当初每个关注点都集中在一个中央,而不是扩散到多处代码;其次,服务模块更简洁,因为它们只蕴含次要关注点(或者外围性能)的代码,而主要关注点的代码被移转到切面中了。

AOP不可能取代 OOP,它只是OOP的无意补充

Spring中的AOP

AOP:实质上就是 Spring动静代理开发,有益于原始类的保护

Spring AOP中的动静代理次要有两种形式,JDK动静代理和CGLIB动静代理。JDK动静代理通过反射来接管被代理的类,并且要求被代理的类必须实现一个接口。JDK动静代理的外围是InvocationHandler接口和Proxy类。

如果指标类没有实现接口,那么Spring AOP会抉择应用CGLIB来动静代理指标类。CGLIB(Code Generation Library),是一个代码生成的类库,能够在运行时动静的生成某个类的子类,留神,CGLIB是通过继承的形式做的动静代理,因而如果某个类被标记为final,那么它是无奈应用CGLIB做动静代理的,诸如private的办法也是不能够作为切面的。

JDK动静代理的实现

代理创立三要素:1 原始对象 2 额定性能 3 代理对象实现雷同的接口

JDK动静代理的外围是InvocationHandler接口和Proxy类。

public static void main(String[] args) {    //创立原始对象    UserService userService = new UserServiceImpl();    //JDK创立动静代理        Proxy.newProxyInstance(ClassLoader ,interfaces, invocationHandler)}
public interface InvocationHandler {    //用于书写额定性能 额定性能:原始办法执行前后 抛出异样    // 参数:Proxy 疏忽掉,示意的是代理对象    //method 额定性能所减少给的那个原始办法    //Object[] args 原始办法的参数    public Object invoke(Object proxy, Method method, Object[] args)        throws Throwable;}

interfaces:原始对象所实现的接口
userService.getClass().getInterfaces()

类加载器的作用:

  • 通过类加载器把对应类的字节码加载到JVM中
  • 通过类加载器创立class对象,进而创立这个类的对象

如何取得类加载器:每个类的.class文件 主动调配与之对应的ClassLoder

在动静代理创立的过程中,须要ClassLoader创立代理类的Class对象,可是动静代理类没有对应的.class文件,JVM也不会为其调配ClassLoader,然而又须要怎么办?(借用一个ClossLoader)

ClassLoader:实现代理类的创立
创立代理类的class对象,进而实现代理类的创立

//留神:类加载器是借用来的 能够随表找一个借用// 在JDK8.0之前 外部变量拜访内部变量须要加finalpublic class JDKProxy {    public static void main(String[] args) {        final UserService  userService = new UserServiceImpl();        InvocationHandler handler = new InvocationHandler() {            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                System.out.println("-----login-------");                //原办法运行                Object obj = method.invoke(userService, args);                return obj;            }        };        UserService service = (UserService) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), userService.getClass().getInterfaces(), handler);        service.login("gewei","hello");        service.register(new User());    }}

CGlib动静代理的实现

对于一些没有实现接口的办法

public class UserServiceImpl(){    login();    register();}

代理类 继承你要代理的类

public clss Proxy extends UserServiceImpl(){    login(){         额定性能         super.login();    }}
public class TestCglib {    public static void main(final String[] args) {        //创立原始对象       final UserService userService = new UserService();    /*        通过cglib形式创立动静代理对象        Proxy.newProxyInstance(ClassLoader ,interfaces, invocationHandler)        cglib同样也须要做这些:        enhancer.setClassLoader();        enhancer.setSuperclass();        enhancer.setCallback(); -->MethodInterceptor(cglib包下)     */        Enhancer enhancer = new Enhancer();        enhancer.setClassLoader(TestCglib.class.getClassLoader());        enhancer.setSuperclass(userService.getClass());        MethodInterceptor interceptor = new MethodInterceptor() {            //等同于 InvocationHandler -- invoke            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {                System.out.println("hello world");                Object invoke = method.invoke(userService, args);                return invoke;            }        };        enhancer.setCallback(interceptor);        UserService userServiceProxy = (UserService) enhancer.create();        userServiceProxy.login();        userServiceProxy.register();    }}

Spring中基于AspectJ注解的AOP编程

环境搭建

    <!-- 1.配置扫描的基包  -->    <context:component-scan base-package="com.itheima"/>    <bean id="Aspectj" class="cn.gewei.factory.Aspectj"></bean>    //关上注解开发<aop:aspectj-autoproxy/>

盘绕告诉

/** * 主要的业务:切面类 */@Component  //把这个类加到Spring容器中@Aspect  //这个类是切面类public class LogAspect {    @Pointcut("execution(* com.itheima.service..*.*(..))")   //切面表达式,这是一个空办法,作用:创立切面表达式的    public void pt() {    }    /**     * 盘绕告诉     */    @Around("pt()")    public Object around(ProceedingJoinPoint joinPoint) {        Object result = null;        try {            System.out.println("前置告诉");            //调用指标办法            result = joinPoint.proceed();            System.out.println("后置告诉");        } catch (Throwable throwable) {            throwable.printStackTrace();            System.out.println("异样告诉");        } finally {            System.out.println("最终告诉");        }        //返回办法的返回值        return result;    }}

前置,后置,异样,最终告诉

/** * 主要的业务:切面类 */@Component  //把这个类加到Spring容器中@Aspect  //这个类是切面类public class LogAspect {    @Pointcut("execution(* com.itheima.service..*.*(..))")   //切面表达式,这是一个空办法,作用:创立切面表达式的    public void pt() {    }    @Before("pt()")    public void before() {        System.out.println("前置告诉");    }    @AfterReturning("pt()")    public void afterReturn() {        System.out.println("后置告诉");    }    @AfterThrowing("pt()")    public void afterThrowing() {        System.out.println("异样告诉");    }    @After("pt()")    public void after() {        System.out.println("最终告诉");    }}

切入点复用

@Pointcut("execution(* *(..))")public void pointcut(){}@Around(value = "pointcut()")

默认状况下Spring底层是JDK动静代理实现的

//将proxy-target-class设为true就是基于Cglib的开发模式<aop:aspectj-autoproxy proxy-target-class="true"/>

小结

AOP是面向对象编程的一个弱小补充。通过Spring的动静代理,咱们当初能够把之前扩散在利用各处的行为放入可重用的模块中。咱们显示地申明在何处如何利用该行为。这无效缩小了代码冗余,并让咱们的类关注本身的次要性能。

AOP编程概念(Spring动静代理开发),通过代理类为原始类减少额定的性能,益处:利于原始类的保护。

最初

感激你看到这里,看完有什么的不懂的能够在评论区问我,感觉文章对你有帮忙的话记得给我点个赞,每天都会分享java相干技术文章或行业资讯,欢送大家关注和转发文章!