spring学习2

使用注解配置spring

步骤:  

  1. 导包4(core/bean/context/spel)+1(logging)+spring-aop包(新版spring需要导入这个包)

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

  3. 开启使用注解代理配置文件

<context:component-scan base-package="com.domain">  指定扫描 com.domain包下面所有类的注解(同时会扫描子包里面的类)

  4. 在类中使用注解完成配置

@Component("user")public class User {
    private String name;
    private Integer age;
    
    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;
    }
    @Override
    public String toString() {
        return "User [name=" + name + ", age=" + age + ", car=" + car + "]";
    }
}

将对象注册到容器

@Component(“user”) 

@Service(“user”)  service层

@Controller(“user”)  web层

@Repository(“user”)  dao层

本质上这四个功能都是一样  只是为了见名知意

修改对象的作用范围

@Scope(scopeName=”prototype”) 指定对象的作用范围         同样也是作用在实体上面

值类型注入

@Value("tom")
private String name;

通过反射来为Field赋值 ,但是这样破坏了封装性

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

@Value("24")
public void setAge(Integer age) {
    this.age = age;
}

引用类型注入

1.使用AutoWired 自动装配

@Component("user")
public class User {
    @Autowired
    private Car car;

        setCar/getCar ...
}

@Component
class Car{
    private String cName;
    private String color;
get/set ... } 注意:使用自动装配,被装配的字段 也要在容器有 可以没有名字

这种方式有一个坏处:如果匹配多个类型一致的对象,将无法选择具体注入哪一个对象

解决办法:使用 Qualifier("car")  通过该注解来告诉 spring容器自动装配哪个名称的对象

注意:Qualifier和AutoWired要一起使用

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

@Resource(name="car")
private Car car;

初始化 | 销毁方法

@PostConstruct                      // 在对象被创建以后调用   相当于配置文件中定义的init-method 
public void init() {
    System.out.println("init method");
}
    
@PreDestroy                       // 在对象被销毁前调用        destory-method
public void destory(){
    System.out.println("destory method");
}                                                

spring与junit整合测试

1.导包    4+2+aop+test

2.配置注解

@RunWith(SpringJUnit4ClassRunner.class)      // 帮我们创建容器
@ContextConfiguration("classpath:applicationContext.xml")  //指定创建容器时使用的配置文件
public class Student {
    
    @Value("wanglei")
    private String name;
    
    @Test
    public void test() {
        System.out.println(name);
    }
    
    @Value("24")
    private Integer age;
    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;
    }
}

spring中的aop

aop思想介绍  横向重复代码 ,纵向抽取

例如:解决乱码问题   管理事务  action拦截器

spring中的aop概念 ------> spring能够为容器中管理的对象生成动态代理对象

以前我们要使用动态代理,需要自己调用下面的方法

Proxy.newProxyInstance(xx,xx,xx) 生成代理对象

现在spring能够帮助我们生成代理对象

spring实现aop的原理

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

 2.cglib代理(没有接口) : 第三方代理技术,cglib代理可以对任何类生成代理,代理的原理是对目标对象进行继承代理.

    但是如果目标对象被final修饰,那么该类无法被cglib代理.

步骤:

  1.创建service的接口是实现类

  

public interface UserService {
    void save();
    void add();
    void delete();
    void find();
}

public class UserServiceIml implements UserService {
    public void save() {
        System.out.println("save");
    }
    public void add() {
        System.out.println("add");
    }
    public void delete() {
        System.out.println("delete");
    }
    public void find() {
        System.out.println("find");
    }
}

  2.使用cglib代理生成代理对象

public class Test implements MethodInterceptor{
    
    public UserService getService() {
        Enhancer en=new Enhancer();   //用于生成代理对象
        en.setSuperclass(UserServiceIml.class);//对谁设置代理
        en.setCallback(this); //代理要做什么
        UserService service = (UserService) en.create();//创建代理对象
        return service;
    }
    
    @Override           proxyObj 目标类的实例  method 目标类方法的反射实例   arg 参数  methodProxy 代理类实例            
    public Object intercept(Object proxyObj, Method method, Object[] arg, MethodProxy methodProxy) throws Throwable {
        System.out.println("打开事务!");
        Object returnValue = methodProxy.invokeSuper(proxyObj, arg);
        System.out.println("提交事务!");
        return returnValue;
    }    
}

   3.测试

public static void main(String[] args) {
        Test test = new Test();
        UserService service = test.getService();
        service.save();
}

AOP名词学习

Joinpoint(连接点):目标对象中,所有可以增强的方法

Pointcut(切入点): 目标对象,已经增强的方法

Advice(通知/增强):增强的代码

Target(目标对象): 被代理的对象

Weaving(织入):将通知应用到切入点的过程

Proxy(代理):将通知织入到目标对象之后,形成代理对象

Aspect(切面):切入点 + 通知

spring中的aop演示

 步骤:

1.导包4+2

        aop包 + aspect包 + aopalliance + weaver 

 

2.准备目标对象

 

3.准备通知

     前置通知   目标方法运行之前调用

     后置通知(如果出现异常不会调用)  在目标方法运行之后调用

     环绕通知   在目标方法之前和之后都调用

     异常拦截通知:如果出现异常,就会调用

     后置通知(无论是否出现异常都会调用) :在目标方法运行之后调用

public class MyAdvice {
    //前置通知
    public void before() {
        System.out.println("前置通知");
    }
    //后置通知
    public void afterReturn() {
        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 after() {
        System.out.println("后置通知(出现异常也会调用)");
    }
}

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

    准备工作:导入AOP(约束)命名空间

    1.配置目标对象  将具体的实现类(而不是接口添加进来)   因为是为 实现类来创建代理对象

      <bean name="userService" class="..."></bean>

    2.配置通知对象

      <bean name="myAdvice" class="...">

    3.配置切入点

     <aop:pointcut expression="execution(* cn.itcast.service.*ServiceImpl.*(..))" id="pc"/>

execution有以下几种形式

public void cn.itcast.service.UserServiceImpl.save()  具体的某个方法
void cn.itcast.service.UserServiceImpl.save()   
* cn.itcast.service.UserServiceImpl.save()      任意返回值
* cn.itcast.service.UserServiceImpl.*()           任意方法名/任意返回值
* cn.itcast.service.*ServiceImpl.*(..)              任意参数/ 任意返回值/ 任意方法名
* cn.itcast.service..*ServiceImpl.*(..)       还会找这个下面的子包

<aop:config>
        <aop:pointcut expression="execution(* com.domin.*Service.*(..))" id="pc"/>
        <aop:aspect ref="advice">
            <aop:before method="before" pointcut-ref="pc"/>
            <aop:around method="around" pointcut-ref="pc"/>
            <aop:after-throwing method="afterException" pointcut-ref="pc"/>
            <aop:after method="after" pointcut-ref="pc"/>
            <aop:after-returning method="afterReturn" pointcut-ref="pc"/>
        </aop:aspect>
</aop:config>

调用顺序

1.没有发生异常的情况下

     前置通知
     这是环绕通知之前的部分
     save method
     这是环绕通知之后的部分
    后置通知(出现异常也会调用)
    后置通知(如果出现异常不会被调用)

2.发生异常的情况下  

    前置通知
    这是环绕通知之前的部分
    出现异常了
    后置通知(出现异常也会调用)

 注解配置实现动态代理

1.导包

2.配置

  同样需要加入  <bean name="userService" class="..."></bean>  和 <bean name="myAdvice" class="...">

3.使用注解来实现代理

4.在配置文件中加入 <aop:aspectj-autoproxy></aop:aspectj-autoproxy>  表示开启使用注解完成织入

5.测试

猜你喜欢

转载自www.cnblogs.com/escapist/p/9038618.html