Spring 四天学习笔记 _day2

Spring框架注解配置与AOP详解

1. 注解配置Spring   


1.1注解代替配置文件:步骤

          1.为配置文件配置新的命名空间

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


           3. 在类中使用注解 完成配置(如果是新版本的spring 框架需要加上一个spring-aop-4.2.4.RELEASE.jar

               4. 因为在项目开发中 ,需要明确的分明注解所在的位置, 所以衍生出来了, 一些功能一样,但是用于表表示的注解


         5. 对象是单实例, 还是多实例 ? 用@Scope  这个注解 , 里面的参数scopeName  有两个属性, singleton(多例)|prototype(单例)  如下


           6.属性注入

                  直接写在属性的头上(通过反射的fild 赋值) 破坏了对象的封装性( 回顾:)

	   // 暴力反射  获取所有的 属性  破坏了 对象的封装
	@Test
	public void test2() throws Exception {
		 Field[] fields = User.class.getDeclaredFields();  


		 for (Field field : fields) {
			System.out.println(field);
		}
		 
	}
	


            

                    写在set 方法的头上(通过set 方法进行赋值)

            

    如果在注解中, 只有一个值需要赋值, 而且赋值的属性是value 可以省略key=         

        7.对象注入

                    1.  第一种方式 : 自动装配(在容器中自动搜索Car 类型的对象, 但是如果容器中, 有两个同样类型的对象, 怎么找? 

                首先对bean 加上@component

                

                然后对属性加  

            

            @Autowited 这个注解,有个问题: 如果匹配多个类型一直的对象, 将无法选择注入哪个对象

            

            我们用@qualifier 这个注解辅助@Acutowired  然后就能实现, 选定那个对象

           这两个注解制定一个对象, 显的有点麻烦所以, 

                

            推荐使用:  直接用个@resource制定键值对, 然后直接加载对象

              2. 第二种方法: 直接在配置文件中配置

       1.2 .  init  和destory  方法  

                用注解@PostConstruct   和@PreDestroy   这样在构造方法执行后就会执行这个方法, (对象被构造之后 执行这个方法 相当于initmethod 方法)

             

            

1.3 STS插件

        1. 手动安装插件(成功率比较低)

           2. 使用老师的eclipse 

           3. spring 装好插件的eclipse 

是否安装成功,右击applicationContext.xml  open with  然后有没有带锤子的文件

1.4 spring 整合junit测试

        1.导包spring-test-4.2.4.RELEASE.jar 导入测试包

            2.测试

         @RunWith(SpringJUnit4ClassRunner.class)   自动创建容器 

          @ContextConfiguration("classpath:applicationContext.xml")   加载配置文件的地址

         有了这两个注解我们不用每次使用时候创建容器对象,然后取出对象, 我们只需要一次把容器创建然后 ,用@Resource(name="user") 然后直接赋值给变量,整个类都可以调用 ,方便了开发, 提高了开发效率

        

2. Spring AOP 

  2.1 aop 思想介绍  

           横向重复, 纵向抽取

    2.2.  spring 动态代理(spring 生成代理对象)

           2.21     spring   能够为管理的容器中的对象生成代理对象

            之前我们要实现动态代理我们要调用整个方法 proxy .newproxyinstance(xx,xx,xx)生成代理对象  ,现在spring 直接帮我们解决

        什么是 springaop  ? 

            比如我们service  层我们写公用的代码, 然后直接 每个service 都要走整个代理的代码

        2.3 spring是实现aop 的原理(动态代理, cglib代理)

        动态代理  :被代理对象必须要实现接口, 才能产生代理对象, 如果 没有接口, 就不能实现动态代理

        cglib代理 : 因为动态代理的缺陷, spring 引用了第三方代理技术, cglib  这种代理是通过, 对目标对象的继承代理  , 就是这个被代理的 对象是 代理对象的父类(如果目标对象呗final 修饰, 那么该类无法被cglib 代理)

        复习 :  

     定义接口        

    

package com.zzq.Service;


public interface UserService {

	void save (); 
	void update (); 
	void delete (); 
	void findAll (); 
}

  定义实现类

package com.zzq.Service.impl;

import com.zzq.Service.UserService;

public class UserServiceImpl implements UserService {

	public void save() {
		// TODO Auto-generated method stub
		System.out.println("保存用户");
	}

	public void update() {
		// TODO Auto-generated method stub
		System.out.println("更新用户");
	}

	public void delete() {
		// TODO Auto-generated method stub
		System.out.println("删除用户");
	}

	public void findAll() {
		// TODO Auto-generated method stub
		System.out.println("查找用户");
	}

	
}

     动态代理工厂 

    

package com.zzq.proxy;

import java.lang.reflect.InvocationHandler;

public class UserServiceProxyFactory implements InvocationHandler {

	
	
	
	public UserServiceProxyFactory(UserService us) {
		super();
		this.us = us;
	}

	private UserService us;
	
	public UserService getUserServiceProxy(){
		//生成动态代理
		UserService usProxy = (UserService) Proxy.newProxyInstance(
									UserServiceProxyFactory.class.getClassLoader(),
									UserServiceImpl.class.getInterfaces(), 
									this
									
				);
		//返回
		return usProxy;
		
	}

	public Object invoke(Object arg0, Method method, Object[] arg2) throws Throwable {
		System.out.println("打开事务!");
		Object invoke = method.invoke(us, arg2);
		System.out.println("提交事务!");
		return invoke;
	}

}








    Cglib代理 工厂的创建 

package com.zzq.proxy;


import java.lang.reflect.Method;

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

import com.zzq.Service.UserService;
import com.zzq.Service.impl.UserServiceImpl;

/**
 * cglib代理
 * @author ZZQ.Hacker
 *
 */
public class UserServiceProxyFactory2 implements  MethodInterceptor  {

	public UserService getUserServiceProxy(){
		
		Enhancer en = new Enhancer();//帮我们生成代理对象
		
		en.setSuperclass(UserServiceImpl.class);//设置对谁进行代理
		
		en.setCallback(this);//代理要做什么
		
		UserService us = (UserService) en.create();//创建代理对象
		
		return us;
	}

	public Object intercept(Object prxoyobj, Method method, Object[] arg, MethodProxy methodProxy) throws Throwable {
		//打开事务
		System.out.println("打开事务!");
		//调用原有方法
		Object returnValue = methodProxy.invokeSuper(prxoyobj, arg);
		//提交事务
		System.out.println("提交事务!");
		
		return returnValue;
	}

	

}










    测试类 , 调用代理对象

package com.zzq.proxy;

import org.junit.Test;

import com.zzq.Service.UserService;
import com.zzq.Service.impl.UserServiceImpl;

public class Demo {

	@Test
	public void test(){
		UserService userService = new UserServiceImpl() ; 
		UserServiceProxyFactory  factory = new UserServiceProxyFactory(userService); 
		UserService uproxy = factory.getUserServiceProxy(); 
		uproxy.save();

		
	}
	
	
	
	@Test
	public void  test2(){
		UserServiceProxyFactory2 factory = new UserServiceProxyFactory2() ; 
		UserService usp    = factory.getUserServiceProxy(); 
		usp.findAll();
		 
		System.out.println(usp instanceof UserServiceImpl);   // 判断代理对象是否属于代理对象的类型, 由于是继承关系 所以一定是true 90
	}
}

    通过

System.out.println(usp instanceof UserServiceImpl); 

 我们可以看出 caglib代理 是通过继承的代理  

    动态代理  是代理对象 与被代理对象直接没有关系, 同时实现了同一个接口, 没有继承关系 

2.4 aop  名词学习

       joinpoint(连接点) : 目标中, 所有可以增强的方法( 这里举个例子 : 比如老师手里有一把刀,那么,学生就是链接点,因为老师有可能捅死每个学生, 有一天真的愤怒了直接捅死一个, 这个一个或者多个, 就是切入点)

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

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

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

        weaving(织入): 将通知织入切点 (把同之应用到链接点 形成切入点)

        proxy (代理)  : 将通知,植入目标代理对象, 之后这个过程叫代理

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

3.spring aop 演示

          3.1步骤 : 

                  1.导包

                    com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar  织入包(第三方包)

                  com.springsource.org.aopalliance-1.0.0.jar     aop 联盟包(第三方包)

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

                    2. 准备目标对象

                    3.准备通知(MyAdvice)

                       

package com.zzq.springaop;


import org.aspectj.lang.ProceedingJoinPoint;


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 after(){
		System.out.println("这是后置通知(出现异常也会调用)!!");
	}
}

                    4.通知进行织入目标对象

          1.导入aop 约束

          2.配置配置文件

            

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd ">

<!-- 准备工作: 导入aop(约束)命名空间 -->
<!-- 1.配置目标对象 -->
	<bean name="userService" class="com.zzq.Service.impl.UserServiceImpl" ></bean>
<!-- 2.配置通知对象 -->
	<bean name="myAdvice" class="com.zzq.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.*(..)
		-->
		<aop:pointcut expression="execution( * com.zzq.Service.impl..*ServiceImpl.*(..))" id="pc"/>
		<aop:aspect ref="myAdvice" >
			<!-- 指定名为before方法作为前置通知 -->
			<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>
</beans>

    3. 进行测试

        

package com.zzq.springaop;

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;

import com.zzq.Service.UserService;


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:com/zzq/springaop/applicationContext.xml")
public class Demo {
	@Resource(name="userService")
	private UserService us;
	
	@Test
	public void fun1(){
		us.delete();;
	}
	
}
4.aop 整理


     1. 面向切面编程思想(跨语言跨平台, 跨物种)横向重复代码, 纵向抽取代码

     2.动态代理, 可以体现aop思想 ,把对象中的方法进行增强(接口)

     3.spring aop 开发 spring 封装了动态代理代码,我们就不用手写动态代理方法了, 还封装了 第三方代理, cglib (继承)代理,可以对任何类进行代理

    4.spring 中的名词

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

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

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

        weaving(织入): 将通知织入切点 (把同之应用到链接点 形成切入点)

        proxy (代理)  : 将通知,植入目标代理对象, 之后这个过程叫代理

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

5.spring 注解配置(了解)

            

    







        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值