Spring的IOC注解开发与AOP

一 IOC实现的注解形式

1SpringAOP的常用注解

   官方建议使用这三个衍生注解,层次清晰,针对每一层
  @Controller web层
  @Service service层
  @Responsitory dao层

@Autowired 注入对象,按类型注入。我们一般都是按照名称来注入,加一个Qualifier注解,必须让@Autowired和@Qualifier一起来使用,来完成按照名称的属性注入,
一般属性用value,对象属性用Resource

代码实现:

(1)编写UserDao的接口

package com.itheima.demo1;

public interface UserDao {
    public void save();
}

(2) 将UserDao 交给Spring管理

Spring的IOC注解开发与AOP

(3)编写UserDao的实现类

package com.itheima.demo1;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;
//标记数据访问组件,即UserDao
@Repository("UserDao")
public class UserDaoImpl implements UserDao {
    @Value("花花")
    private String name;
    @Override
    public void save() {
        System.out.println("UseDao的save方法执行了"+"        姓名是"+name);
    }
}

(4)测试类

public class TestDemo1 {
    /**
     * 使用注解的方式实现
     * demo1使用的是UserDao
     */
    @Test
    public void demo1(){
     ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao= (UserDao) applicationContext.getBean("UserDao");
        userDao.save();
    }
    }

运行成功的结果图:

Spring的IOC注解开发与AOP

 


 

 

2 Bean作用的作用范围的注解(重点):

  @scope
    singleton:单例
    prototype:多例

3 Bean的声明周期的注解

   初始化的注解:PostCostrucct
   销毁的注解:PerDestroy

代码片段

Spring的IOC注解开发与AOP

 

 4XML和注解的比较

  XML:适合任何场景               特点:结构清晰,方便维护
  注解:有些地方用不了(这个类不是自己提供的)  特点:开发方便
XML和注解整合开发(各取所长),XML管理Bean、注解属性注入

二 AOP的开发

1 什么是AOP?

AOP为Aspect Oriented Programming的缩写,意为:面向切面编程。AOP是OOP的扩展、延申,解决oop开发遇到的问题。

利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

2 AOP采用的是横向抽取机制(代理机制)取代了传统的纵向继承.

Spring底层的AOP实现原理是动态代理
  jdk的动态代理:只能对实现接口的类实现动态代理
  Cglib动态代理(类似于Javassist第三方的动态代理)

3  jdk的动态代理部分代码实现

jdkProxy类

package com.baidu.demo;

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

public class JdkProxy implements InvocationHandler {
    private UserService userService;
    //把增强的对象传到proxy中

   public JdkProxy(UserService userService) {
        this.userService=userService;
    }

     public UserService createProxy(){
            UserService Userproxy=(UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), this);//当时这里写错了
          return Userproxy;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //如果是save方法,那么就加强
        if("save".equals(method.getName())){
            System.out.println("权限校验成功了.............");
            return method.invoke(userService,args);
        }
        return method.invoke(userService,args);
    }
}

4 Cglib动态代理的部分代码实现

package com.baidu.demo2;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CglibProxy implements MethodInterceptor {
    //把要增强的类传进来
    CustomerDao customerDao=new CustomerDao();

    public CglibProxy(CustomerDao customerDao) {
        this.customerDao = customerDao;
    }
    public CustomerDao createProxy(){
        Enhancer enhancer=new Enhancer();
        //设置父类
        enhancer.setSuperclass(customerDao.getClass());
        //设置回调
        enhancer.setCallback(this);
        CustomerDao customerDao = (CustomerDao) enhancer.create();
        return customerDao;
    }

    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        //判断方法是否为空
        if("save".equals(method.getName())){
            //增强
            System.out.println("权限校验成功啦.....");
            return methodProxy.invokeSuper(proxy,args);
        }
        return methodProxy.invokeSuper(proxy,args);
    }
}

 

5  Spring AOP的开发(基于Aspect J的XML方式)
  你要想进行AOP的开发,就必须得了解一些相关的术语

    Joinpoint:只要被拦截的点就成为连接点
    Pointcut:切入点,真正被拦截到的点
    Advice:通知、增强 增强的方法称为是通知,在方法执行之前,称为前置通知。日志记录、性能监控称为是后置通知 
    Introduction:引介。类层面的增强
    Target:被增强的对象
    Weaving:织入。通知应用(action)到目标Target的过程
    Proxy:织入之后产生了一个代理对象
    Aspect:切面多个通知和多个切入点的组合

6 Spring AOP的XML开发

通知类型(前三个是我们用的比较多的)
1前置通知            获得切入点的信息
2后置通知            获得返回值的类型,afterreturning
3环绕通知(功能最强的一个通知)   proceed
4异常抛出通知          用于抛出异常的
5最终通知
无论有没有异常,最终通知总会执行的

  (1)Aspect类

Spring的IOC注解开发与AOP
package com.baidu.demo3;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

/**
 * 这是一个切面类
 */
public class aspetctJXMl {
    /**
     * 前置通知
     * @param joinPoint
     */
    //增强权限校验,提供增强的方法
    public void checkPri(JoinPoint joinPoint) {
        System.out.println("权限已经校验啦....." + joinPoint);
    }

    /**
     * 后置通知
     * @param result
     * @return
     */
    public String log(Object result){
        System.out.println("日志已经记录下来了....."+result);
        return "aa";
    }

    /**
     * 环绕通知,功能最强的一个
     * @param proceedingJoinPoint
     * @return
     */
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕之前.......");
        Object proceed = proceedingJoinPoint.proceed();
        System.out.println("环绕之后.......");
        return proceed;
    }

    /**
     * 异常抛出通知
     */
    public void afterThrowable(Throwable th){
        System.out.println("异常抛出通知执行了....."+th);
    }
    /**
     * 最终通知
     */
    public void Final(){
        System.out.println("最终通知执行了");
    }
}
View Code

   (2)在xml中的配置

Spring的IOC注解开发与AOP
<?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 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 definitions here -->
    <bean id="productDao" class="com.baidu.demo3.ProductDaoImpl"/>
    <!--将切面类交给spring管理-->
    <bean id="aspect" class="com.baidu.demo3.aspetctJXMl"/>
    <!--AOP的配置-->
    <aop:config>
        <aop:pointcut id="product1" expression="execution(* com.baidu.demo3.ProductDaoImpl.save(..))"/>
        <aop:pointcut id="product2" expression="execution(* com.baidu.demo3.ProductDaoImpl.delete(..))"/>
        <aop:pointcut id="product3" expression="execution(* com.baidu.demo3.ProductDaoImpl.update(..))"/>
        <aop:pointcut id="product4" expression="execution(* com.baidu.demo3.ProductDaoImpl.find(..))"/>

        <!--配置切面-->
        <aop:aspect ref="aspect">
            <!--前置通知-->
            <aop:before method="checkPri" pointcut-ref="product1"/>
            <!--后置通知-->
            <aop:after-returning method="log" pointcut-ref="product2" returning="result"/>
            <!--环绕通知-->
            <aop:around method="around" pointcut-ref="product3" />
            <!--异常抛出通知-->
            <aop:after-throwing method="afterThrowable" pointcut-ref="product4" throwing="th"/>
            <!--最终通知-->
            <aop:after method="Final" pointcut-ref="product4"/>
        </aop:aspect>
    </aop:config>
</beans>
View Code

7 SPring AOP的注解开发

  (1)Aspect类

package com.baidu.demo4;

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

@Component  //组件
@Aspect     //切面多个通知和多个切入点的组合
public class aspect {
    //声明一个公共的切入点
    @Pointcut("execution(* com.baidu.demo4.UserService.*(..))") //任意返回值  任意方法   任意参数
    public void myPointCut() {
    }

    //增强的方法
    @Before("myPointCut()")
    public void log() {
        System.out.println("日志记录成功啦===============");
    }

    @After("myPointCut()")
    public void save() {
        System.out.println("性能检测成功啦=============");
    }

    @AfterThrowing("myPointCut()")
    public void b() {
        System.out.println("检测出来了异常===============");
    }
}

(2)zhujie.xml

Spring的IOC注解开发与AOP

 (3)测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:zhujie.xml")
public class SpringTest2 {
    @Resource
    private UserService userService;

    @Test
    public void demo(){
        userService.find();
        userService.save();
        userService.delete();
    }
}

最后,附上一节的Spring框架的快速入门   https://www.cnblogs.com/bao6/p/10388760.html

英文单词:Component:组件

上一篇:Spring -bean的装配和注解的使用


下一篇:新手学习笔记之Spring编写AOP半自动代理