Spring2~~~

打印 上一主题 下一主题

主题 455|帖子 455|积分 1365

注解配置Bean



   Spring的 IOC 容器检查到注解就会天生对象,但这个注解的详细含义不会辨认 
    配置自动扫描的包

  1.     <!--配置容器要扫描的包
  2.     1. component-scan 要对指定包下的类进行扫描, 并创建对象到容器
  3.     2. base-package 指定要扫描的包
  4.     3. 含义是当spring容器创建/初始化时,就会扫描com.hspedu.spring.component包
  5.        下的所有的 有注解 @Controller / @Service / @Respository / @Component类
  6.        将其实例化,生成对象,放入到ioc容器
  7.     -->
  8.     <context:component-scan base-package="com.hspedu.spring.component"/>
复制代码

Map里的默认id是类名开头小写
com.hspedu.spring.component会扫描comonent及其子包
假如要扫描spring下的包,写成com.hspedu.spring.* 


只扫描包下的哪些类

在xml中加上 resource-pattern="User*.class" 表现只扫描spring.component 和它的子包下的User打头的类,用的比较少
  1. <context:component-scan base-package="com.hspedu.spring.component"
  2. resource-pattern="User*.class" />
复制代码
清除包下某种类型的注解(注解方式)

  1.     <!--
  2.         需求:如果我们希望排除某个包/子包下的某种类型的注解,可以通过exclude-filter来指定
  3.         1. context:exclude-filter 指定要排除哪些类
  4.         2. type 指定排除方式 annotation表示按照注解来排除
  5.         3. expression="org.springframework.stereotype.Service" 指定要排除的注解的全路径
  6.     -->
  7.     <context:component-scan base-package="com.hspedu.spring.component">
  8.         <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
  9.         <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
  10.     </context:component-scan>
复制代码
指定自动扫描哪些注解类(注解方式)

  1.     <!--
  2.         需求:如果我们希望按照自己的规则,来扫描包/子包下的某些注解, 可以通过 include-filter
  3.         1. use-default-filters="false" 表示不使用默认的过滤机制/扫描机制
  4.         2. context:include-filter 表示要去扫描哪些类
  5.         3. type="annotation" 按照注解方式来扫描/过滤
  6.         4. expression="org.springframework.stereotype.Service" 指定要扫描的注解的全路径
  7.     -->
  8.     <context:component-scan base-package="com.hspedu.spring.component" use-default-filters="false">
  9.        <context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
  10.        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
  11.        <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
  12.     </context:component-scan>
复制代码

使用 value 指定 id 值


        覆盖默认的id值
        注解默认 类名首字母小写 作为id值

  1. @Service(value = "sss")
  2. public class Student {
  3. }
复制代码
自动装配

@AutoWired


   IOC容器中有多个对象,要举行查找
1、是否有唯一bean
2、根据id查找

  根据id查找没找到,报错缘故原由:按id找不到,按类型有多个,类型匹配不上
  根据唯一性查找,属性名无所谓,直接按照类型找到
IOC容器中的对象和装配的对象哈希值不肯定一样

  1.     <!--自动扫描的id就是类名首字母小写或者指定value的id值-->
  2.     <context:component-scan
  3.             base-package="com.hspedu.spring.component"/>
  4.     <!--配置两个UserService对象-->
  5.     <bean class="com.hspedu.spring.component.UserService" id="userService200"/>
  6.     <bean class="com.hspedu.spring.component.UserService" id="userService300"/>
复制代码
  1. @Controller
  2. public class UserAction {
  3.     @Autowired
  4.     private UserService userService200;
  5.     public void sayOk() {
  6.         System.out.println("userAction 装配的 userService属性=" + userService);
  7.         userService200.hi();
  8.     }
  9. }
复制代码
@Qualifier与@AutoWired

必须搭配使用,相当于@Resource

@Resource


 按照name的值在容器中查找,属性名没有作用了

按照type类型查找,属性名没有作用了,要求在容器里只能有一个如许类型的对象 
  

假如没有指定name和type,则先试用byName注入策略,假如匹配不上,再使用byType策略

泛型依靠装配











           使用Autowired
        把PhoneDao对象装配到PhoneService,
通过泛型传入BaseDao,再把指定的泛型对象装配到PhoneService
  
动态署理 

不改变原有代码的情况下举行对象功能加强,使用署理对象拓展功能
  1. public interface Vehicle {
  2.     public void run();
  3.     public String fly(int height);
  4. }
复制代码
  1. public class Car implements Vehicle{
  2.     @Override
  3.     public void run() {
  4.         //System.out.println("交通工具开始运行了....");
  5.         System.out.println("小汽车在路上 running....");
  6.         //System.out.println("交通工具停止运行了....");
  7.     }
  8.     @Override
  9.     public String fly(int height) {
  10.         System.out.println("小汽车可以飞翔 高度=" + height);
  11.         return "小汽车可以飞翔 高度=" + height;
  12.     }
  13. }
复制代码
 类似切面类

  1. public class VehicleProxyProvider {
  2.    
  3.     //target_vehicle 表示真正要执行的对象
  4.     //该对象的类实现了Vehicle接口
  5.     private Vehicle target_vehicle;
  6.    
  7.     public VehicleProxyProvider(Vehicle target_vehicle) {
  8.         this.target_vehicle = target_vehicle;
  9.     }
  10.     //编写一个方法,可以返回一个代理对象, 该代理对象可以通过反射机制调用到被代理对象的方法
  11.     public Vehicle getProxy() {
  12.         
  13.         ClassLoader classLoader =
  14.                 target_vehicle.getClass().getClassLoader();
  15.         //得到对象的接口信息
  16.         Class<?>[] interfaces = target_vehicle.getClass().getInterfaces();
  17.         //创建InvocationHandler 对象
  18.         //因为 InvocationHandler 是接口,所以我们可以通过匿名对象的方式来创建该对象
  19.         /**
  20.          *
  21.          * public interface InvocationHandler {
  22.          *  public Object invoke(Object proxy, Method method, Object[] args)
  23.          *         throws Throwable;
  24.          * }
  25.          * invoke 方法是将来执行我们的target_vehicle的方法时,会调用到
  26.          *
  27.          */
  28.         InvocationHandler invocationHandler = new InvocationHandler() {
  29.             /**
  30.              * invoke 方法是将来执行我们的target_vehicle的方法时,会调用到
  31.              * @param o 表示代理对象
  32.              * @param method 就是通过代理对象调用方法时,的哪个方法 代理对象.run()
  33.              * @param args : 表示调用 代理对象.run(xx) 传入的参数
  34.              * @return 表示 代理对象.run(xx) 执行后的结果.
  35.              * @throws Throwable
  36.              */
  37.             @Override
  38.             public Object invoke(Object o, Method method, Object[] args)
  39.                     throws Throwable {
  40.                 System.out.println("交通工具开始运行了....");
  41.                 //method 是?: public abstract void com.hspedu.spring.proxy2.Vehicle.run()
  42.                 //target_vehicle 是? Ship对象
  43.                 //args 是null
  44.                 //这里通过反射+动态绑定机制,就会执行到被代理对象的方法
  45.                 Object result = method.invoke(target_vehicle, args);
  46.                 System.out.println("交通工具停止运行了....");
  47.                 return result;
  48.             }
  49.         };
  50.         /*
  51.           public static Object newProxyInstance(ClassLoader loader,
  52.                                           Class<?>[] interfaces,
  53.                                           InvocationHandler h)
  54.           1. Proxy.newProxyInstance() 可以返回一个代理对象
  55.           2. ClassLoader loader: 类的加载器.
  56.           3. Class<?>[] interfaces 就是将来要代理的对象的接口信息
  57.           4. InvocationHandler h 调用处理器/对象 有一个非常重要的方法invoke
  58.          */
  59.         Vehicle proxy =
  60.                 (Vehicle)Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
  61.         return proxy;
  62.     }
  63. }
复制代码
Test类 

  1.     @Test
  2.     public void proxyRun() {
  3.         //创建VehicleProxyProvider对象, 并且我们传入的要代理的对象
  4.         VehicleProxyProvider vehicleProxyProvider =
  5.                 new VehicleProxyProvider(new Car());
  6.         //获取代理对象, 该对象可以代理执行方法
  7.         //proxy的编译类型是 Vehicle, 运行类型是 class com.sun.proxy.$Proxy9
  8.         Vehicle proxy = vehicleProxyProvider.getProxy();
  9.         //当执行run方法时,会执行到 代理对象的invoke
  10.         proxy.run();
  11.         String result = proxy.fly(10000);
  12.         System.out.println("result=" + result);
  13.     }
复制代码
getProxy()的缺点


   硬编码,功能不强,希望以方法的情势来实行一段业务
  写成方法,耦合度高
  1.     //在目标对象执行前执行
  2.     public void before(Method method, Object[] args) {
  3.         System.out.println("before-方法执行前-日志-方法名-" + method.getName() + "-参数 "
  4.                 + Arrays.asList(args)); //这里从AOP看,就是一个横切关注点-前置通知
  5.     }
  6.     //在目标对象执行后执行
  7.     public void after(Method method, Object result) {
  8.         System.out.println("after-方法执行正常结束-日志-方法名-" + method.getName() + "-结果result= "
  9.                 + result);//从AOP看, 也是一个横切关注点-返回通知
  10.     }
复制代码
举行解耦,写成AOP类,复用性差,不灵活,硬编码
  1. public class HspAOP {
  2.     public static void before(Method method, Object[] args) {}
  3.     public static void after(Method method, Object result) {}
  4. }
复制代码
AOP

面向切面编程



快速入门

 


环绕通知可以将四个通知合并管理
  1. public interface SmartAnimalable {
  2.     //求和
  3.     float getSum(float i, float j);
  4.     //求差
  5.     float getSub(float i, float j);
  6. }
复制代码
  1. @Component //使用@Component 当spring容器启动时,将 SmartDog注入到容器
  2. public class SmartDog implements SmartAnimalable {
  3.     @Override
  4.     public float getSum(float i, float j) {
  5.         float result = i + j;
  6.         System.out.println("方法内部打印result = " + result);
  7.         return result;
  8.     }
  9.     @Override
  10.     public float getSub(float i, float j) {
  11.         float result = i - j;
  12.         System.out.println("方法内部打印result = " + result);
  13.         return result;
  14.     }
  15. }
复制代码
切面类 

   
  

  • @Before(value = "") 表现前置通知        
    value = "execution(public float spring.aop.aspectj.SmartDog.getSum(float, float)       
    指定切入到哪个类的哪个方法  情势是: 访问修饰符 返回类型 全类名.方法名(形参列表)
  • showBeginLog方法可以明白成就是一个切入方法
  • JoinPoint joinPoint 在底层实行时,由AspectJ切面框架, 会给该切入方法传入 joinPoint对象,通过该方法,步伐员可以获取到 相关信息
  1. @Aspect //表示是一个切面类
  2. @Component //会注入SmartAnimalAspect到容器
  3. public class SmartAnimalAspect {
  4.     @Before(value = "execution(public float spring.aspectj.SmartDog.getSum(float, float))")
  5.     public void showBeginLog(JoinPoint joinPoint) {
  6.         //通过连接点对象joinPoint 可以获取方法签名
  7.         //invoke(Object proxy, Method method, Object[] args)整合到joinPoint
  8.         Signature signature = joinPoint.getSignature();
  9.         System.out.println(signature.getName() + "-参数 "
  10.                 + Arrays.asList(joinPoint.getArgs()));
  11.     }
  12. }
复制代码
XML开启AOP功能

  1.     <context:component-scan
  2.             base-package="com.hspedu.spring.aop.aspectj"/>
  3.     <!-- 开启基于注解的AOP功能 -->
  4.     <aop:aspectj-autoproxy/>
复制代码
假如不开启,.getClass()不会得到署理对象,只会得到当前运行的对象(相当于new)
Test类

  1.     @Test
  2.     public void smartDogTestByProxy() {
  3.         ApplicationContext ioc =
  4.                 new ClassPathXmlApplicationContext("beans08.xml");
  5.         //需要通过接口类型来获取到注入的SmartDog对象-就是代理对象
  6.         SmartAnimalable smartAnimalable =
  7.                 ioc.getBean(SmartAnimalable.class);
  8.         //SmartAnimalable smartAnimalable =
  9.         //        (SmartAnimalable)ioc.getBean("smartDog");
  10.         smartAnimalable.getSum(10, 2);
  11.     }
复制代码
  从前是new一个对象,得到这个类的的署理对象
  动态署理返回的对象是个署理对象,强转成接口的情势返回
  Animal proxy =
          (Animal)Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
  return proxy;
(xml中开启AOP)如今通过接口类型获取的对象就是这个类的署理对象
  细节


   按接口来获取,多个类实现了接口会报错
UsbInterface interface = ioc.getBean(UsbInterface.class);

  
  interface是署理对象,获取Phone类的署理对象,getBean()就相当于之前的getPorxy()
UsbInterface interface = (UsbInterface)ioc.getBean(Phone.class);
UsbInterface interface = (UsbInterface)ioc.getBean("phone");

  切入表达式





重用



  1.     //定义一个切入点, 在后面使用时可以直接引用, 提高了复用性
  2.     @Pointcut(value = "execution(public float spring.aspectj.SmartDog.getSum(float, float)))")
  3.     public void myPointCut() {}
  4.     @Before(value = "myPointCut()")
  5.     public void showBeginLog(JoinPoint joinPoint) {}
  6.     @AfterReturning(value = "myPointCut()", returning = "res")
  7.     public void showSuccessEndLog(JoinPoint joinPoint, Object res) {}
  8.     @AfterThrowing(value = "myPointCut()", throwing = "throwable")
  9.     public void showExceptionLog(JoinPoint joinPoint, Throwable throwable) {}
复制代码

 


两种动态署理

jdk的Proxy

面向接口,只能加强实现类中接口中存在的方法
得到的对象是JDK署理对象的实例

天生的署理对象只能转换成接口不能转换成被署理类
 
Spring的CGlib

面向父类,可以加强父类的所有方法
得到的对象是被署理对象的子类


JoinPoint常用方法


返回通知中获取结果



   在@AfterReturning 增加属性 , 比如 returning = "res",同时在切入方法增加 Object res
留意: returning = "res" 和 Object res 的 res名字一致

   非常通知中获取非常



环绕通知 

  1. @Aspect
  2. @Component
  3. public class SmartAnimalAspect {
  4.     //演示环绕通知的使用-了解
  5.     //1. @Around: 表示这是一个环绕通知[完成其它四个通知的功能]
  6.     //2. value = "execution(public float com.hspedu.spring.aop.aspectj.SmartDog.getSum(float, float)) 切入点表达式
  7.     //3. doAround 表示要切入的方法 - 调用结构 try-catch-finally
  8.     @Around(value = "execution(public float com.hspedu.spring.aop.aspectj.SmartDog.getSum(float, float))")
  9.     public Object doAround(ProceedingJoinPoint joinPoint) {
  10.         Object result = null;
  11.         String methodName = joinPoint.getSignature().getName();
  12.         try {
  13.             //1.相当于前置通知完成的事情
  14.             Object[] args = joinPoint.getArgs();
  15.             List<Object> argList = Arrays.asList(args);
  16.             System.out.println("AOP环绕通知[-前置通知]" + methodName + "方法开始了--参数有:" + argList);
  17.             //在环绕通知中一定要调用joinPoint.proceed()来执行目标方法
  18.             result = joinPoint.proceed();
  19.             //2.相当于返回通知完成的事情
  20.             System.out.println("AOP环绕通知[-返回通知]" + methodName + "方法结束了--结果是:" + result);
  21.         } catch (Throwable throwable) {
  22.             //3.相当于异常通知完成的事情
  23.             System.out.println("AOP环绕通知[-异常通知]" + methodName + "方法抛异常了--异常对象:" + throwable);
  24.         } finally {
  25.             //4.相当于最终通知完成的事情
  26.             System.out.println("AOP环绕通知[-后置通知]" + methodName + "方法最终结束了...");
  27.         }
  28.         return result;
  29.     }
  30. }
复制代码
切面优先级

   假如同一个方法,有多个切面在同一个切入点切入,优先级如何控制
  @order(value = n) 来控制,n 越小,优先级越高
  前置通知通过@order来判断顺序
  



基于XML配置AOP 

  1. public interface SmartAnimalable {
  2.     float getSum(float i, float j);
  3.     float getSub(float i, float j);
  4. }
复制代码
  1. public class SmartDog implements SmartAnimalable {
  2.     @Override
  3.     public float getSum(float i, float j) {return result;}
  4.     @Override
  5.     public float getSub(float i, float j) {return result;}
  6. }
复制代码
切面类将注解全部去掉 
  1. public class SmartAnimalAspect {
  2.     public void showBeginLog(JoinPoint joinPoint) {}
  3.     public void showSuccessEndLog(JoinPoint joinPoint, Object res) {}
  4.     public void showExceptionLog(JoinPoint joinPoint, Throwable throwable) {}
  5.     public void showFinallyEndLog(JoinPoint joinPoint) {}
  6. }
复制代码
测试类 
  1.     @Test
  2.     public void testAspectByXML() {
  3.         ApplicationContext ioc = new ClassPathXmlApplicationContext("beans09.xml");
  4.         SmartAnimalable smartAnimalable =
  5.                 ioc.getBean(SmartAnimalable.class);
  6.         smartAnimalable.getSum(10, 2);
  7.     }
复制代码
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.        xmlns:context="http://www.springframework.org/schema/context"
  5.        xmlns:aop="http://www.springframework.org/schema/aop"
  6.        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
  7.     <!--使用XML配置,完成AOP编程-->
  8.     <!--配置一个切面类对象-bean-->
  9.     <bean class="com.hspedu.spring.aop.xml.SmartAnimalAspect" id="smartAnimalAspect"/>
  10.     <!--配置一个SmartDog对象-bean-->
  11.     <bean class="com.hspedu.spring.aop.xml.SmartDog" id="smartDog"/>
  12.     <!--配置切面类, 细节一定要引入 xmlns:aop-->
  13.     <aop:config>
  14.         <!--配置切入点-->
  15.         <aop:pointcut id="myPointCut" expression="execution(public float com.hspedu.spring.aop.xml.SmartDog.getSum(float, float)))"/>
  16.         <!--配置切面的前置,返回, 异常, 最终通知-->
  17.         <aop:aspect ref="smartAnimalAspect" order="10">
  18.             <!--配置前置通知-->
  19.             <aop:before method="showBeginLog" pointcut-ref="myPointCut"/>
  20.             <!--返回通知-->
  21.             <aop:after-returning method="showSuccessEndLog" pointcut-ref="myPointCut" returning="res"/>
  22.             <!--异常通知-->
  23.             <aop:after-throwing method="showExceptionLog" pointcut-ref="myPointCut" throwing="throwable"/>
  24.             <!--最终通知-->
  25.             <aop:after method="showFinallyEndLog" pointcut-ref="myPointCut"/>
  26.             <!--配置环绕通知-->
  27.             <!--<aop:around method=""/>-->
  28.         </aop:aspect>
  29.     </aop:config>
  30. </beans>
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

大连密封材料

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表