使用注解实现 控制反转 IOC

  • 注解方式将Bean的定义信息和Bean实现类结合在一起,Spring提供的注解有:
  • @Component:实现Bean组件的定义。注解的参数相当于bean标签的id名称,可以省略不写,省略不写默认为当前类名首字母小写。
@Component("user")
public class User {
}
  • @Autowired注解实现Bean的自动装配,默认按类型匹配,可以使用@Qualifier指定Bean的名称。
    @Autowired如果加到属性上边,是可以不用生成set方法。因为底层会使用反射将属性的访问修饰符改成public的,然后给属性赋值 (使用的更多)。如果希望还是set方法给属性赋值,可以生成set方法,将@Autowired加到set方法上
  • @Scope(“singleton | prototype”):默认对象的创建是单例模式,为了让action每次都创建,需要给Action上边加上@Scope(“prototype”)注解。
通过@component衍生的三个注解
  1. Spring为了代码的可读性,spring框架又推出了下边三个注解。下边三个注解和第一个注解的作用是完全一样的,就是为了规范。
  • @Controller 加到Action类上边,代表这是一个控制器
  • @Service 加到Service实现类上边,代表这是一个业务逻辑层的类
  • @Repository 加到Dao实现类上边,代表这是操作数据库的
  • 注:由于我们现在使用的mybatis框架,所以@Repository注解是不需要使用的

注:如果一个接口有两个或多实现类,使用@Autowired自动装配会报错.
解决方案:使用精准装配

  • 例如:
  1. service起上名字
  2. 在@Autowired 下边增加一个注解 @Qualifier
// 代码演示
@Service("userService01")
public class UserServiceImpl01 implements UserService{
}
// 另外的一个类需要引用
@Autowired
@Qualifier("userService01")
private UserService userService;

spring扫描项目中的注解

  • context标签
  • 配置包名,告诉spring框架扫描那个包(子包)的注解,凡是类上边带有spring注解的类都会被加入到spring工厂中。
<!--spring扫描项目中的注解,指定需要扫描的基类包,多个包可用逗号隔开-->
    <context:component-scan base-package="com.kgc"/>

使用@Resource注解实现组件装配,默认按名称匹配

  • @Resource的作用相当于@Autowired。只不过@Autowired按byType自动注入,而@Resource默认按 byName自动注入。
  • @Resource有两个属性是比较重要的,分是name和type,Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。
  • @Resource装配顺序
      1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
      2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
      3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
      4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;
  • 示例:
@Service("userService") 
public class UserServiceImpl implements UserService { 
	// 为dao属性注入名为userDao的Bean
	@Resource(name = "userDao")
	private UserDao dao; 
}
@Service("userService") 
public class UserServiceImpl implements UserService { 
	// 查找名为dao的Bean,并注入给dao属性
	@Resource
	private UserDao dao; 
}

使用注解定义切面

  • AspectJ
  • 面向切面的框架,它扩展了Java语言,定义了AOP 语法,能够在编译期提供代码的织入
  • @AspectJ
  • AspectJ jdk5新增的功能,使用JDK 5.0 注解技术和正规的AspectJ切点表达式语言描述切面
  • Spring通过集成AspectJ实现了以注解的方式定义增强类,大大减少了配置文件中的工作量
  • 利用轻量级的字节码处理框架asm处理@AspectJ中所描述的方法参数名

注:使用@AspectJ,首先要保证所用的JDK 是5.0或以上版本

使用步骤:
  1. 在xml配置文件中启用对于@AspectJ注解的支持(配置标签:<aop:aspectj-autoproxy />)。
<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:p="http://www.springframework.org/schema/p" 
       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/aop
       https://www.springframework.org/schema/aop/spring-aop.xsd 
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd">

    <!--spring扫描项目中的注解,指定需要扫描的基类包,多个包可用逗号隔开-->
    <context:component-scan base-package="com.kgc"/>
    <!--启用对于@AspectJ注解的支持-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
  1. 编写额外功能类、添加一些需要增强的方法
@Component
@Aspect
public class PrepositionExtra{

    Logger logger = Logger.getLogger(PrepositionExtra.class);
	// 通过Pointcut注解配置在一个自定义方法上可以让其他的增强方法进行统一匹配
    @Pointcut("execution(* com.kgc.entity.*.*(..))")
    public void mycat(){}

    /**
     * 前置增强
     * Arrays.toString(joinPoint.getArgs()):连接点方法参数数组
     * @param joinPoint 连接点对象
     */
    @Before("mycat()")
    public void beforeMethod(JoinPoint joinPoint){
        logger.debug("前置增强:" + joinPoint.getSignature().getName() + Arrays.toString(joinPoint.getArgs()));
    }

    /**
     * 一个后置增强
     * getThis():连接点方法所在的目标类
     * getSignature():连接点方法信息
     * @param joinPoint
     * @param o
     */
    @AfterReturning("mycat()")
    public void afterReturningMethod(JoinPoint joinPoint){
        logger.debug("后置增强:" + joinPoint.getThis() + joinPoint.getSignature());
    }

    /**
     * 异常增强
     * @param joinPoint
     * @param e
     */
    @AfterThrowing(pointcut="mycat()" , throwing = "e")
    public void excetionMethod(JoinPoint joinPoint , Exception e){
        System.out.println("这里是异常增强!!!!!");
    }

    /**
     * 环绕增强
     */
    @Around("mycat()")
    public void aroudmethod(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕增强之前");
        joinPoint.proceed();
        System.out.println("环绕增强之后");
    }

    /**
     * 最终增强
     * @param joinPoint
     */
    @After("mycat()")
    public void aftermethod(JoinPoint joinPoint){
        System.out.println("最终增强。。。。。。。。。。。。。");
    }

}