spring中文参考手册-核心技术 aop

spring aop,面向切面编程;

1,用途:在日志,登陆等重复无关业务逻辑的部分抽象出来;

2,原理:java动态代理;

java.lang.reflect.Proxy;

 

切面:需要执行的代码x(),比如插入的日志代码;

切入点:需要插入的位置,比如add()方法前面,后面....

通知:一个普通的类->有特定功能的类: 

可以通过a,继承各种类;b,实现接口;3,注解,4,配置;

 

通知: 

1,前置通知,在执行add()方法前执行;

2,后置通知,在执行add()方法正常执行后执行;

3,环绕通知:可以是前置|后置|异常时执行;

4,异常通知:程序异常才执行;

20160805211132669.

在applicationContext.xml配置aop

<bean id="logBefore" class="xxx.xxx.xxx">

</bean>

<!--将 切入点 和 通知 进行关联-->

<aop:config>

  <aop:pointcut expression="execution(public void org.service.Student.addStudent(Student stu))">

  <aop:advisor advice-ref="logBefore" poincut-ref="pointcut"/>

</aop:config>

    <!--将通知纳入springIOC容器-->
    <bean id="notice" class=""></bean>

    <aop:config>
        <!--切入点,需要执行代码的地方-->
        <aop:pointcut id="pointcut" expression="execution(public * xx.xxx.function(paramtype))"/>
        <!--需要执行的代码 -->
        <aop:advisor advice-ref="notice" pointcut-ref="pointcut"/>
    </aop:config>

说明:在任何addStudent方法前面,执行logBefore方法;

使用步骤:

1,通知类,普通实现通知接口;

2,业务类,业务方法:

3,配置: 将通知类,业务类纳入springIOC容器,xml中配置aop:config关联切入点和通知类

 

环绕通知:(本质是拦截器)

public class LogAround implements MethodInterceptor {

    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        Object result=null;
        // 目标方法返回值
        try{
            //前置通知执行代码
            result = methodInvocation.proceed();
            //后置通知执行代码
        }catch (Exception e)        {
            //异常通知执行代码
        }
        return result;
    }
}

配置:

  <bean id="LogAround" class="com.maotu.control.LogAround"></bean>
    
    <aop:config>
        <!--切入点,需要执行代码的地方-->
        <aop:pointcut id="pointcut2" expression="execution(public * xx.xxx.addStudent(paramtype))"/>
        <!--需要执行的代码 -->
        <aop:advisor advice-ref="LogAround" pointcut-ref="pointcut2"/>
    </aop:config>

环绕通知可以获取目标方法的一切控制权:是否执行,执行前代码,执行后代码,执行返回值更改;

 

二,使用注解实现通知,aop

开启注解:

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

1,设置扫描器:扫描注解所在的包

<context:component-scan base-package=""></context:component-scan>

2,配置: 将通知类,业务类纳入springIOC容器,xml中配置aop:config关联切入点和通知


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Component("logAroundAnno")
@Aspect
public class LogAroundAnno {

    @Before("execution(public * addStudent(..))") //属性:定义切点
    public void myBefore(JoinPoint jp)
    {
        System.out.println("基于注解的前置通知,目标对象:"+jp.getTarget()+",方法名:"+jp.getSignature().getName()+",参数列表:"+ Arrays.toString(jp.getArgs())+";");
    }

    @AfterReturning(pointcut = "execution(public * addStudent(..))",returning = "returnValue") //属性:定义切点
    public void myAfter(JoinPoint jp,Object returnValue)
    {
        System.out.println("基于注解的后置通知,目标对象:"+jp.getTarget()+",方法名:"+jp.getSignature().getName()+",参数列表:"+ Arrays.toString(jp.getArgs())+";返回值:"+returnValue);
    }

    //只捕获特定异常
    @AfterThrowing(pointcut = "execution(public * addStudent(..))",throwing="e")
    public void myException(JoinPoint jp,NullPointerException e){
        System.out.println("基于注解的异常通知: 只捕获空指针异常:e "+e.getMessage());
    }

    @Around("execution(public * addStudent(..))") //环绕通知
    public void myAround(ProceedingJoinPoint jp){
        try{
            //前置通知
            jp.proceed();
            //后置通知
        }catch (Throwable e)
        {
            //异常通知
        }finally{
            //最终通知
        }
    }

    @After("execution(public * addStudent(..))")
    public void MyAfter(){
        System.out.println("基于注解的最终通知");
    }
}

 

 

 

例子:登陆验证

环境:intelli idea 2018+java 1.8

1,新建spring boot工程:包含登陆页面/login; 主页/index

2,新建拦截器类:

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("----登陆拦截器----");
        if(request.getSession().getAttribute("username")==null)
        {
            response.sendRedirect("/login");
            return  false;
        }
        return true;
    }
}

拦截器继承:HandlerInterceptor ,重载PreHandle方法;如果session中没有用户名,则进入登陆页面;

3,新建登陆适配器:

import com.maotu.gameagent.interceptor.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@SpringBootConfiguration
public class LoginAdapt implements WebMvcConfigurer{

    @Autowired
    private LoginInterceptor loginInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns("/login**");

    }
}

对所有url进行拦截,对登陆页面不拦截;

3,请求映射:

@RequestMapping(value = "/login")
    public String login(HttpServletRequest request){
        String userName = request.getParameter("username");
        if(userName!=null)
        {
            request.getSession().setAttribute("username",userName);
            return  "/agent/index";
        }
        return "/login";
    }


    @RequestMapping("/logout")
    public String logout(HttpServletRequest request)
    {
        try {
            request.getSession().invalidate();
            request.logout();
        } catch (ServletException e) {
            e.printStackTrace();
        }
        return  "/login";
    }

登陆用户,到数据库中验证后,session赋值;退出后清空session。

 

注解形式依赖注入:

1,自动装配,根据类型

@Service("aaa")
@Autowired

2,自动装配,根据名称装配,

@Repository("stuDao")

@Autowired
@Qualifier("stuDao")
private IstudentDao studentDao;

 

转载于:https://my.oschina.net/u/856051/blog/3017882

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值