spring相关知识点二

spring_day02(使用注解配置spring、spring中的aop)

一.使用注解替代xml配置spring
1.使用本地导入新的约束context,此时的XML前缀prefix不能为空,因为前一章节beans设置为空,仅允许一个空的命名空间
2.开启注解代替配置文件
<context:component-scan base-package="cn.itcast.bean"></context:component-scan>
该配置不仅扫描该包,还会扫描该包下所有子包,在加载配置文件时会换可以将其中的"cn.itcast.bean""cn.itcast"替代
3.在类中使用注解完成配置
(1)在类前加注解例如@Component(“user”)或者@Component(value=”user”),其中只有一个变量且是value时才可以不写value,这里”user”相当于给起了个别名,类似于<bean name="user" class="cn.itcast.bean.User"></bean>这种,后面还有@Service、@Controller、@Repository(数据库,用于dao层)这几个就是名字不同实际功能一样
(2)确定User作用范围,默认单例,用法@Scope(scopeName="prototype")
(3)注解属性注入方式:@Value(value=”18”)或者@Value(“18”):属性只有一个时可以省略但属性值必须是value,直接在类中域、属性的前面加上,这种是通过反射Field赋值,会破坏封装,第二种是加到setName()方法上,这种是通过set方法赋值
注意:仍然是先通过空参构造,因为此时检测构造器有初始化输出,然后再使用反射式set方法注入值
对象注入:a.首先将要注入的对象@Component(“xxx”)注册到spring容器中
b.@Autowired 在要注入的属性对象前加上这个,使用自动装配,这里也有个问题,加入spring容器中有多个关于此类的对象该找哪个,例如通过@Component(“xxx”)构造一个对象呢,通过构造一个对象到spring中(但是这两个对象name别名不同),这时spring就有两个对象,此时通过以下方式,例如@Autowired @Qualifier(“xxx”)或者直接手动注入,指定注入哪个名称的对象使用Resource(name=”xxx”),类似于前一章节的<bean name="user" class="cn.itcast.bean.User" init-method="init" destroy-method="destroy"></bean>注解使用@PostConstruct和@PreDestroy来标记,同理,这个bean如果标注@Scope(scopeName=”prototype”),同前一章节一样不会执行销毁方法(注意大小写,这里一个大小写写错出了bug)
4.可以使用Demo测试了

二.spring提示插件安装,spring与Junit的整合测试
(4+2+aop+test共8个包):4个核心包加两个日志包
测试使用高级版注解测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo {
    @Resource(name="user") //从spring容器中找别名为user的对象
    private User u;

    @Test
    public void fun(){
        System.out.println(u);
    }
}

三.AOP思想:横向重复,纵向抽取
spring能够为容器中管理的对象自动生成动态代理对象
以前:Proxy.newProxyInstance(xx,xx,xx) classLoader,Interface[] arr,InvocationHandler handler 第一个参数:类加载器随意取 例如UserServiceProxyFactory.class.getClassLoader(),第二个参数是被代理类对象的所有接口UserServiceImpl.class.getInterfaces(),第三个参数是实现接口类,这里类自己实现InvocationHandler,所以使用this

spring实现aop原理方式:
1.动态代理:被代理对象必须实现接口InvocationHandler,如果没有实现该接口就不能使用动态代理
2.cglib:对任何类生成代理,原理对目标对象进行继承代理,如果该目标对象被final修饰,则该类不能被cglib代理,因为代理对象继承被代理对象
spring同时整合了两种代理(混合式 有接口:动态代理优先 无接口:cglib)
这里使用动态代理、cglib测试将事务插到增删改查中

四.名词学习
Jointpoint(连接点):目标对象中,所有可以增强的方法(例如save()、delete()方法)
PointCut(切入点):目标对象中,已经或者说将要增强的方法
Advice:通知,即增强代码,这里举例:
  System.out.println(“打开事务”);System.out.println(“提交事务”);
Target(目标对象):被代理对象(实例中的userServiceImpl)
Weaving(织入):将通知应用切入点形成代理过程
Proxy(代理):将通知织入目标对象之后形成代理对象
aspect(切面):切入点+通知

五.springAOP的实际应用
1.导包 4+2+2+2(4个核心包+2个日志包+aspects+aop+aop alliance+aspectj.weaver) 加上test共11个包,这里需要导入aop约束 spring-aop-4.2.xsd
2.准备目标对象  准备通知  配置进行织入
(测试构造cn.itcast.a_aspect中MyAdvice.java类)
//前置通知:目标方法进行之前调用
//后置通知:目标方法进行之后调用
//环绕通知:目标方法之前之后都调用
//异常拦截通知:出现异常就会调用
//后置通知(不受干扰):无论是否出现异常都会调用
配置AOP既可以通过xml进行配置

<!-- 准备工作 导入aop约束 -->
<!-- 1.配置目标对象 -->
<bean name="userService" class="cn.itcast.service.UserServiceImpl"></bean>
<!-- 2.配置通知对象 -->
<bean name="myAdvice" class="cn.itcast.d_springaop.MyAdvice"></bean>
<!-- 3.配置将通知置入目标对象 -->
<aop:config>
    <!-- 配置切入点
        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.*(..)

     -->
    <!-- 默认public可不写   *表示所有返回值   *表示所有方法   (..)表示参数任意  切入点目标对象中要增强的方法-->
    <aop:pointcut expression="execution(* cn.itcast.service.*ServiceImpl.*(..))" id="pc"/>

    <!-- 将通知中的方法功能加入到切入点中(即要增强的方法中) -->
    <aop:aspect ref="myAdvice">
        <!-- 前置 -->
        <aop:before method="before" pointcut-ref="pc"/>
        <!-- 后置 -->
        <aop:after-returning method="afterReturning" 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:aspect>
</aop:config>

通过注解配置

applicatonContext.xml
<!-- 准备工作 导入aop约束 -->
<!-- 1.配置目标对象 -->
<bean name="userService" class="cn.itcast.service.UserServiceImpl"></bean>
<!-- 2.配置通知对象 -->
<bean name="myAdvice" class="cn.itcast.e_annotationaop.MyAdvice"></bean>
<!-- 3.开启使用注解完成织入 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

MyAdvice.java

package cn.itcast.e_annotationaop;
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;
@Aspect
//表示这是一个通知类
public class MyAdvice {
@Pointcut("execution(* cn.itcast.service.*ServiceImpl.*(..))")
public void pc(){}

//前置通知
@Before("MyAdvice.pc()")
public void before(){
    System.out.println("这是前置通知!");
}
//后置通知
@AfterReturning("execution(* cn.itcast.service.*ServiceImpl.*(..))")
public void afterReturning(){
    System.out.println("这是后置通知(如果出现异常不会调用!)");
}
//环绕通知
@Around("execution(* cn.itcast.service.*ServiceImpl.*(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable{
    System.out.println("这是环绕通知之前的部分!");
    Object proceed = pjp.proceed();
    System.out.println("这是环绕通知之后的部分!");
    return proceed;

}
//异常通知
@AfterThrowing("execution(* cn.itcast.service.*ServiceImpl.*(..))")
public void afterException(){
    System.out.println("这是异常出现的通知部分!");
}
//后置通知
@After("execution(* cn.itcast.service.*ServiceImpl.*(..))")
public void after(){
    System.out.println("这是后置通知异常出现也调用!");

}

}
AOP:面向切面编程(横向重复代码、纵向抽取)
动态代理:1.可以体现AOP思想
2.可以对目标对象(被代理对象)方法进行增强
AOP封装了动态代理(基于接口)、cglib代理(基于继承)

总结:
注解:@Component、@Controller、@Service、@Repository
@Scope指定对象的作用范围或者是singleton或者是prototype
@Value 值类型定义
@Autowired 自动属性注入
@Qualifier 指定注入对象的名称
@Resource 指定对象的名称name注入
@PostConstruct 对象初始化后执行
@PreDestroy 销毁方法

二.spring AOP思想
体现:filter、动态代理、interceptor(Struts2中)
spring AOP:封装了动态代理技术体现AOP
springAOP实现:
动态代理:代理需要实现接口
cglib:对目标对象继承代理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值