首页 热点资讯 义务教育 高等教育 出国留学 考研考公
您的当前位置:首页正文

JAVAEE框架学习——Spring——注解、aop

2024-12-17 来源:花图问答

Spring注解

步骤

导包4+2+spring-aop

为主配置文件引入新的命名空间(约束)

开启使用注解代替配置文件

  <!--开启注解
    指定扫描 base-package下的所有注解
    -->
    <context:component-scan base-package="cn.probuing.bean"></context:component-scan>

在类中使用注解完成配置

将对象注册到容器

@Component("user")
@Service("user")//service层
@Controller("user")//web层
@Repository("user")//dao层

指定对象的作用范围

//指定对象的作用范围
@Scope(scopeName = "prototype")

值类型注入

    @Value("tom")
    private String name;

通过反射的Field赋值,破坏了封装性

   @Value("JACK")
    public void setName(String name) {
        this.name = name;
    }

通过set方法赋值,推荐使用

引用类型注入

引用类型注入,需要先将引用类型注册到容器中

@Component("car")
public class Car {
    private String name;
    private String color;

    public String getName() {
        return name;
    }

    @Value("BMW")
    public void setName(String name) {
        this.name = name;
    }

    public String getColor() {
        return color;
    }

    @Value("green")
    public void setColor(String color) {
        this.color = color;
    }

    @Override
    public String toString() {
        return "Car{" +
                "name='" + name + '\'' +
                ", color='" + color + '\'' +
                '}';
    }
}
  • 注入方式一:自动装配 自动扫描引用类型
    @Autowired
    private Car car;

这种方式不好的地方在于 如果匹配到多个类型一致的对象将无法选择具体注入的对象可以通过辅助注解解决,指定自动装配的装配对象

@Qualifier("car2")
  • 注入方式二:手动注入,指定注入哪个名称的对象
@Resource(name = "car")
    private Car car;

初始化|销毁方法

  /**
     * 在对象创建后调用 相当于init-method
     */
    @PostConstruct
    public void init() {
        System.out.println("user初始化");
    }

    /**
     * 在销毁方法之前调用
     */
    @PreDestroy 
    public void destroy() {
        System.out.println("user销毁");
    }

Spring与Junit整合测试

1.导包4+2+aop+test

配置详解

创建配置

获得容器对象,测试代码

//帮我们创建容器,并调用指定class的方法
@RunWith(SpringJUnit4ClassRunner.class)
//指定创建容器时使用哪个配置文件
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringJunitDemo {
    //获得Spring管理的对象
    @Resource(name = "user")
    private User u;
    @Test
    public void fun1() {
        System.out.println(u);
    }
}

AOP思想

图片.png

Spring中的AOP

Spring中的AOP

Spring实现aop的原理

动态代理

被代理对象必须要实现接口,才能产生代理对象,如果没有接口将不能使用动态代理技术

cglib代理

第三方代理技术,cglib代理.可以对任何类生成代理.代理的原理是对目标对象进行继承代理. 如果目标对象被final修饰.那么该类无法被cglib代理.

aop名词

名词解释

Spring使用aop

Spring使用aop开发就是指的是:Spring封装了动态代理的代码,还封装了cglib,我们不需要手写动态代理代码

xml配置方式

导包

spring-aspects-4.2.4.RELEASE.jar
spring-aop-4.2.4.RELEASE.jar

  • 第三方包
    com.springsource.org.aopalliance-1.0.0.jar
    com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

准备目标对象

准备通知

public class MyAdvice {
    //前置通知
//    |-目标方法运行之前调用
    public void before() {
        System.out.println("这是前置通知");
    }

    //后置通知(如果出现异常)
//    |-在目标方法运行之后调用
    public void afterReturning() {
        System.out.println("这是后置通知 出现异常不会调用");
    }

    //环绕通知
//    |-在目标方法之前和之后都调用
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("环绕通知——之前");
        //调用目标方法
        Object proceed = pjp.proceed();
        System.out.println("环绕通知——之后");
        return proceed;
    }
    //异常拦截通知
//    |-出现异常,调用
    public void afterException() {
        System.out.println("出现异常");
    }
    public void afer() {
        System.out.println("后置通知,出现异常也会调用");
    }
}

配置进行织入,将通知织入目标对象中

 <!--配置目标对象-->
    <bean name="userServiceTarget" class="cn.probuing.proxy.UserServiceImpl"/>
    <!--配置通知对象-->
    <bean name="myAdvice" class="cn.probuing.advice.MyAdvice"/>
    <!--配置将通知置入目标对象-->
    <aop:config>
        <!--配置切入点-->
        <aop:pointcut id="pc" expression="execution(* cn.probuing.proxy..*ServiceImpl.*(..))"/>
        <!--描述通知-->
        <aop:aspect ref="myAdvice">
            <!--前置通知-->
            <aop:before method="before" pointcut-ref="pc"/>
            <!--后置通知-->
            <aop:after method="afer" pointcut-ref="pc"/>
            <!--后置通知 异常不关闭-->
            <aop:after-returning method="afterReturning" pointcut-ref="pc"/>
            <!--异常拦截通知-->
            <aop:after-throwing method="afterException" pointcut-ref="pc"/>
            <!--环绕通知-->
            <aop:around method="around" pointcut-ref="pc"/>
        </aop:aspect>
    </aop:config>

测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:cn/probuing/aop/applicationContext.xml")
public class AopTest {
    @Resource(name = "userService")
    private UserService u;
    @Test
    public void fun1() {
        u.save();
    }
}

注解配置方式

  • 通知定义

    /**
     * 抽取切点
     */
    @Pointcut("execution(* cn.probuing.proxy..*ServiceImpl.*(..))")
    public void pc() {

    }

    //前置通知
//    |-目标方法运行之前调用
    @Before("MyAdvice.pc()")
    public void before() {
        System.out.println("这是前置通知(注解方式)");
    }

    //后置通知(如果出现异常)
//    |-在目标方法运行之后调用
    @AfterReturning("MyAdvice.pc()")
    public void afterReturning() {
        System.out.println("这是后置通知 出现异常不会调用(注解方式)");
    }

    //环绕通知
//    |-在目标方法之前和之后都调用
    @Around("MyAdvice.pc()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("环绕通知——之前(注解方式)");
        //调用目标方法
        Object proceed = pjp.proceed();
        int i = 1 / 0;
        System.out.println("环绕通知——之后(注解方式)");
        return proceed;
    }

    //异常拦截通知
//    |-出现异常,调用
    @AfterThrowing("MyAdvice.pc()")
    public void afterException() {
        System.out.println("出现异常(注解方式)");

    }

    @After("MyAdvice.pc()")
    public void afer() {
        System.out.println("后置通知,出现异常也会调用(注解方式)");
    }
  • 配置方式
<?xml version="1.0" encoding="UTF-8"?>
<beans 
        
          
    <!--配置目标对象-->
    <bean name="userService" class="cn.probuing.proxy.UserServiceImpl"/>
    <!--配置通知对象-->
    <bean name="myAdvice" class="cn.probuing.annotationaop.MyAdvice"/>
    <!--开启使用注解完成织入-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
显示全文