spring IOC 和 AOP 动态代理 和静态代理 区别的原理

spring IOC 和 AOP 动态代理 和静态代理 区别的原理

一、Ioc

ioc控制反转,最开始主动权在程序猿手中,各个模块依赖在一起。现在主动权在调用者手中,模块和模块之间没有强依赖的关系了,ioc容器进行bean对象的管理。

二、bean的作用域

singleton (单例),prototype(多例),request,session,application,webscoket

三、代理模式

静态代理 和 动态代理;springAop的底层原理

① 静态代理

角色分析:

​ 抽象角色:一般会使用接口或者抽象类来解决

​ 真实角色:被代理的角色

​ 代理角色:代理真实角色,代理真实角色后,我们一般会做一写附属操作

静态代理,代理类需要实现被代理接口的所有方法,增加了代码

package com.wp.single.daili.staticstate;

import com.wp.single.daili.dynamicstate.UserService;

// 静态代理类Proxy,需要实现UserService中所有的方法
public class Proxy implements UserService {

    private UserService userService;

    public Proxy() {}
	
    // 进行set方法注入
    public Proxy(UserService userService) {
        this.userService = userService;
    }

    @Override
    public void add(Integer type) throws Exception {
        System.out.println("添加日志");
        userService.add(type);
    }
}

public static void main(String[] args) throws Exception {
        UserService userService = new UserServiceImpl();
        Proxy proxy = new Proxy(userService);

        proxy.add(1);
}

// 输出:添加日志 以及 + add()方法的内容

静态代理模式的好处:

​ ① 可以使真实角色的操作更加纯粹!,不用去关注一些公共的业务!

​ ② 公共业务也就交给代理角色,实现了业务的分工!

​ ③ 公共业务发生扩展的时候,方便集中管理!

缺点:

​ 一个真实角色就会产生一个代理角色;

② 动态代理
  1. 动态代理和静态代理角色一样

  2. 动态代理的代理类是动态生成的,不是我们直接写好的

  3. 动态代理分为两类:基于接口的动态代理;基于类的动态代理

基于接口:JDK动态代理

基于类:cglib

java字节码实现:javasist

代理类的生成和执行
package com.example.demo.daili;

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

public class UserProxy implements InvocationHandler {

    private UserService userService;

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    // 通过调用getProxy方法生成代理类
    public Object getProxy () {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                userService.getClass().getInterfaces(),this);
    }

    // 指定方法,在方法的前后进行增强
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("执行方法前");
        Object obj = method.invoke(userService,args);
        System.out.println("执行方法后");
        return obj;
    }
}

public static void main(String[] args) {
        UserProxy userProxy = new UserProxy();

        UserService userService = new UserServiceImpl();
    	// 进行set方法注入
        userProxy.setUserService(userService);

        UserService service = (UserService)userProxy.getProxy();
        service.save();
    }

四、Aop的核心机制

① 通过xml配置的形式进行切面

<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
    http://www.springframework.org/schema/aop/spring-aop.xsd">
	
    
    <bean id="userService" class="com.wupan.test.UserServiceImpl"/>
    <bean id="log" class="com.wupan.log.Log"/>
    <bean id="afterlog" class="com.wupan.log.AfterLog"/>

    <aop:config>
         
        <aop:pointcut id="ponit" expression="execution(* com.wupan.test.UserServiceImpl.*(..))"/>

        
        <aop:advisor advice-ref="afterlog" pointcut-ref="ponit"/>
        <aop:advisor advice-ref="log" pointcut-ref="ponit"/>
    aop:config>

beans>
package com.wupan.log;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

// 实现AfterReturningAdvice,实现后置通知
public class AfterLog implements AfterReturningAdvice {
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("AfterLog类,returnValue:" + returnValue + ",method:" + method+ ",target:" + target);
    }
}

// 实现MethodBeforeAdvice方法进行前置通知
public class Log implements MethodBeforeAdvice {
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("Log类,method:" + method + ",Object:" + o);
    }
}


public static void main(String[] args) {
     // 加载applicationContext.xml,将对象加载入bean容器中
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
     	// 获取bean实例
        UserService userService = (UserService)applicationContext.getBean("userService");
     // 执行UserService中的方法
        userService.add();
}
② 自定义切入点类
package com.wupan.diy;

// 自定义切面类 Diy01 
public class Diy01 {

    public void before () {
        System.out.println("前置通知Diy01");
    }

    public void after () {
        System.out.println("后置通知Diy01");
    }
}

public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService)applicationContext.getBean("userService");
        userService.add();
    }

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

    <bean id="userService" class="com.wupan.test.UserServiceImpl"/>
	
    <bean id="diy01" class="com.wupan.diy.Diy01"/>

    <aop:config>
        
        <aop:aspect id="aspect01" ref="diy01">
            
            <aop:pointcut id="point" expression="execution(* com.wupan.test.UserServiceImpl.*(..))"/>
			
            <aop:before method="before" pointcut-ref="point"/>
            <aop:after method="after" pointcut-ref="point"/>
        aop:aspect>
    aop:config>
beans>
③ 开起注解支持
package com.wupan.zujie;

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;

// 定义切面注解
@Aspect
public class ZhuJieJava {
	
    // 定义通知 和 切入点
    @Before("execution(* com.wupan.test.UserServiceImpl.*(..))")
    public void before () {
        System.out.println("===before===");
    }

    @After("execution(* com.wupan.test.UserServiceImpl.*(..))")
    public void after () {
        System.out.println("===after===");
    }

    @Around("execution(* com.wupan.test.UserServiceImpl.*(..))")
    public void around (ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("方法执行前");
        joinPoint.proceed();
        System.out.println("方法执行后");
    }
}

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

    <bean id="userService" class="com.wupan.test.UserServiceImpl"/>

    <bean id="accept" class="com.wupan.zujie.ZhuJieJava"/>
	
    
    <aop:aspectj-autoproxy/>
beans>

五、aop进行权限的校验

@RestController
public class Controller {

    @RequestMapping("/getmessage")
    public String getMessage () {
        return "ok";
    }

}

@Aspect
@Component
@EnableAspectJAutoProxy
public class AspectTest {

    @Autowired
    HttpServletRequest request;

    // 定义环绕通知
    @Around("execution(* com.example.demo.controller.Controller.*(..))")
    public Object around (ProceedingJoinPoint point) throws Throwable {
        String a = request.getParameter("a");
        if ("2".equals(a)) {
            // 定义条件,不满足则没有权限
            return "没有权限!";
        } else {
            // 有权限执行方法
            point.proceed();
        }
        return "ok";
    }
}

你可能感兴趣的:(spring,java,aop,动态代理,静态代理)