Spring入门02

一、使用注解配置Spring

一、注解准备

1、引入新的名称空间,并导入aop包,在xml中配置注解

<?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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- bean definitions here -->

<!-- 指定扫描domain包下的所有类中的注解。
    注意:扫描包时,会扫描指定包下的所有子孙包
 -->
<context:component-scan base-package="domain"></context:component-scan>


</beans>

2、常用注解说明

将对象交给spring容器

@Component("name")

相当于<bean name="name" class="class"></bean>

@Servlce  service层

@Controller  web层

@Repository  dao层

以上3个与@Component效果相同,开发中经常使用这三个代表对象属于开发中的哪一层

指定对象作用范围

@Scpoe("singleton")  @Scpoe("prototype") 

是单例还是多例,默认单例,与xml配置中Scope属性一致

值类型注入

@Value(value="张三") 等于@Value("张三")

当注入属性是value时,可以不写value="张三",只写"张三"

值类型注入可以在成员变量上添加注解,也可以在set方法上添加

引用类型注入

方式一、

@Autowired  //自动装配

@Qualifier("user") //告诉spring容器自动装配哪个名称的对象

方式二、

@Resource(name="user")  //手动注入,指定哪个名称的对象

初始化方法与销毁方法注解

@PostConstract  //在对象被创建后调用,init-method

@PreDestroy    //在销毁之前调用,destroy-method

代码案例

//@Component("user")
//@Service("user")//service层
//@Controller("user")//web层
@Repository("user")//dao层
//@Scope("prototype")//指定对象的作用范围
@Scope("singleton")
public class User {

    public User() {
        
        System.out.println("User构造方法执行了");
    }
    
    @Value("张三")//值类型注入
    private String name;
    @Value("20")
    private Integer age;
    
    //引用类型注入方式一、
    //@Autowired//自动装配
    //@Qualifier("car")//告诉spring容器自动装配哪个名称的对象
    //引用类型注入,方式二
    @Resource(name="car")//手动注入,指定注入哪个名称的对象
    private Car car;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public Car getCar() {
        return car;
    }
    public void setCar(Car car) {
        this.car = car;
    }
    @Override 
    public String toString() {
        return "User [name=" + name + ", age=" + age + ", car=" + car + "]";
    }
    
    @PostConstruct//在对象被创建后调用,init-method
    public void init() {
        
        System.out.println("我是初始化方法");
    }
    
    @PreDestroy//在销毁之前调用 destory-method
    public void destory() {
        
        System.out.println("我是销毁方法");
    }
}

 二、spring整合junit进行测试

导入spring-test包

//Spring整合junit进行测试
//需要导入spring-test包

@RunWith(SpringJUnit4ClassRunner.class)//帮我们创建容器
@ContextConfiguration("classpath:applicationContext.xml")//指定创建容器时使用哪一个配置文件
public class SpringTest1 {
    
    //将名为user的对象注入到变量u中
    @Resource(name="user")
    private User u;
    
    @Test
    public void fuc1() 
    {
        
        System.out.println(u);
    }
}

 二、Spring AOP

1、实现原理

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

cglib代理:第三方代理,cglib代理可以对任何类生成代理,代理原理是对目标对象进行继承代理。如果目标对象

      被final修饰,那么该类无法被cglib代理

2、AOP常用名词

JoinPoint(连接点):目标对象中,所有可以增强的方法
PointCut(切入点):目标对象中准备增强或已经增强的方法
Advice(通知/增强):增强的代码
Target(目标对象):被代理对象
Weaving(织入):将通知应用到切入点的过程
Proxy(代理):将通知织入到目标对象后,形成代理对象
aspect(切面):切入点+通知

3、开发步骤

  1、导入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"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- bean definitions here -->

  需要导入的包为:spring基础包

    beans  context  core  express 

  其他包:

    test  web  commons.logging  apache.log4j

  aop包:

    aop  aspects  aopalliance  aspectj.weaver

 

  2、编写目标对象和通知对象

  注意点:在通知对象中的环绕通知

    需要传入参数:

      ProceedingJoinPoint 类型

        ProceedingJonPoint对象执行proceed()方法并将方法的返回对象返回

package AopDemo1;

//目标对象
public class UserTarget {

    public void add() {
        System.out.println("添加用戶");
    }
    
    public void update() {
        int a=1/0;
        System.out.println("修改用戶");
    }
    
    public void delete() {
        System.out.println("刪除用戶");
    }
    
    public void query() {
        System.out.println("查詢用戶");
    }
}
package AopDemo1;

import org.aspectj.lang.ProceedingJoinPoint;

//通知对象
public class MyAdvice {

    /**
     * 前置通知:目标方法运行之前调用
     * 后置通知(如果出现异常不会调用)
     *         :在目标方法运行之后调用
     * 环绕通知:在目标方法之前和之后都调用
     * 异常拦截通知:如果出现异常,就会调用
     * 后置通知(无论是否出现异常,都会调用)
     *         :在目标方法运行之后调用
     * */
    
    //前置通知
    public void before() {
        System.out.println("这是前置通知");
    }
    
    //后置通知
    public void afterReturning() {
        System.out.println("这是后置通知(出现异常则不会调用)");
    }
    
    //环绕通知
    //需要手动执行方法并返回结果
    public Object around(ProceedingJoinPoint pdj) throws Throwable {
        System.out.println("环绕通知之前。。。!");
        Object proceed = pdj.proceed();
        System.out.println("环绕通知之后。。。!");
        return proceed;
    }
    
    //异常拦截通知
    public void afterException() {
        System.out.println("出现异常,请注意!");
    }
    
    //后置通知
    public void after() {
        System.out.println("这是后置通知(即使发生异常也会执行)");
    }
}

  3、将目标对象和通知对象交给Spring容器管理

<!-- 1、配置目标对象 -->
<bean name="userTar" class="AopDemo1.UserTarget"></bean>
<!-- 2、配置通知对象 -->
<bean name="myAdvice" class="AopDemo1.MyAdvice"></bean>

  4、配置 AOP 切入点

  注意点:配置完成切入点表达式后在<aop:pointcut>中

    expression属性:execution(表达式)

<!-- 3、配置切入点 -->
<aop:config>
    <!-- 
        演化过程:
        public void AopDemo1.UserTarget.add()
        void AopDemo1.UserTarget.add()
        * AopDemo1.UserTarget.add() 不管返回类型是什么
        * AopDemo1.UserTarget.*() 不管类中的方法是什么
        * AopDemo1.UserTarget.*(..) 不管方法的参数是什么
        * AopDemo1.*Target.*(..) 类名以Target结尾的所有类的所有方法
     -->
     <!-- 配置要切入的对象,就是切入点 -->
     <aop:pointcut expression="execution(* AopDemo1.*Target.*(..))" id="cut"/>
     <!-- 通知对象为myAdvice -->
     <aop:aspect ref="myAdvice">
         <!-- 指定myAdvice中的before方法作为前置通知,织入到切入点中 -->
         <aop:before method="before" pointcut-ref="cut"/>
         
         <!-- 指定myAdvice中的afterReturning方法作为后置通知(发生异常不执行),织入到切入点中 -->
         <aop:after-returning method="afterReturning" pointcut-ref="cut"/>
         
         <!-- 指定myAdvice中的around方法作为环绕通知,织入到切入点中 -->
         <aop:around method="around" pointcut-ref="cut"/>
         
         <!-- 指定myAdvice中的around方法作为异常拦截通知,织入到切入点中 -->
         <aop:after-throwing method="afterException" pointcut-ref="cut"/>
         
         <aop:after method="after" pointcut-ref="cut"/>
     </aop:aspect>
</aop:config>

   5、测试

package AopDemo1;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:AopDemo1/applicationContext.xml")
public class AopTest {
    
    @Resource(name="userTar")
    private UserTarget user;
    
    @Test
    public void func1() {
        user.add();
        
        //user.update();
    }
}

三、使用注解配置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"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- bean definitions here -->

<!-- 开启依赖注入扫描注解 -->
<context:component-scan base-package="AopDemo2"></context:component-scan>

<!-- 开启AOP 注解完成织入 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

</beans>
package AopDemo2;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Component("myAdvice")
@Aspect    //标识该类为通知类
public class MyAdvice {
    
    @Pointcut("execution(* AopDemo2.*Target.*(..))")
    public void cut() {}
    
    
    //前置通知
    @Before("MyAdvice.cut()")
    public void before() {
        System.out.println("这是前置通知");
    }
    
    
    //后置通知
    @AfterReturning("MyAdvice.cut()")
    public void afterReturning() {
        System.out.println("这是后置通知(出现异常则不会调用)");
    }
    
    //环绕通知
    //需要手动执行方法并返回结果
    @Around("MyAdvice.cut()")
    public Object around(ProceedingJoinPoint pdj) throws Throwable {
        System.out.println("环绕通知之前。。。!");
        Object proceed = pdj.proceed();
        System.out.println("环绕通知之后。。。!");
        return proceed;
    }
    
    //异常拦截通知
    @AfterThrowing("MyAdvice.cut()")
    public void afterException() {
        System.out.println("出现异常,请注意!");
    }
    
    //后置通知
    @After("MyAdvice.cut()")
    public void after() {
        System.out.println("这是后置通知(即使发生异常也会执行)");
    }
    
}
package AopDemo2;

import org.springframework.stereotype.Component;

//目标对象
@Component("userTar")
public class UserTarget {

    public void add() {
        System.out.println("添加用戶");
    }
    
    public void update() {
        int a=1/0;
        System.out.println("修改用戶");
    }
    
    public void delete() {
        System.out.println("刪除用戶");
    }
    
    public void query() {
        System.out.println("查詢用戶");
    }
}
package AopDemo2;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:AopDemo2/applicationContext.xml")
public class AopTest1 {

    @Resource(name="userTar")
    private UserTarget user;
    
    @Test
    public void test() {
        user.add();
        
        
    }
}
原文地址:https://www.cnblogs.com/harriets-zhang/p/13463015.html