Spring专题(7)-Spring注解配置

Spring注解配置

注解技术从JDK5.0推出,之后很多框架开始提供注解配置形式。Spring框架从2.5版本开始支持注解配置。注解配置的优点:简单、快捷。

7.1组件扫描功能

Spring可以按指定的包路径扫描内部的组件,当发现组件类定义前有一下的注解标记,会将该组件纳入Spring容器中。

1)@Component(其他组件)

2)@Controller(Action组件,负责调Service)

3)@Service(Service组件,负责调DAO,处理一些额外逻辑)

4)@Repository(DAO组件,负责访问数据库)

  1. 注意事项:
  1. 括号中的为推荐用法,上述4个注解任意用也可以,但不符合规范。
  2. 注解只能用在类定义前、方法定义前、成员变量定义前!

7.2组件扫描的使用方法

step1:在applicationContext.xml配置文件中开启组件扫描配置

<!-- 开启组件扫描,base-package指定扫描包路径。使用前提:要有xmlns:context命名空间的引入。base-package="org.tarena"这么写,则dao和action都能被扫描-->

       <context:component-scan base-package="org.tarena" />

step2:在要扫描的组件的类定义前使用上述注解标记即可。例如在JdbcCostDAO类前使用

@Repository

public class JdbcCostDAO implements CostDAO {

       public JdbcCostDAO(){        System.out.println("创建CostDAO对象");        }

       @PostConstruct//等价于设置了init-method="方法名"属性

       public void myinit(){     System.out.println("初始化CostDAO对象");            }

       @PreDestroy//等价于设置了destroy-method="方法名"属性

       public void mydestroy(){      System.out.println("销毁CostDAO对象");        }

      ……              ……

@Repository等价于原来配置文件中的:

<bean id="jdbcCostDAO" class="org.tarena.dao.JdbcCostDAO"></bean>

加上@Scope("prototype")等价于原配置文件中的:

<bean id="jdbcCostDAO" scope="prototype" class="org.tarena.dao.JdbcCostDAO"></bean>

  1. 注意事项:
  1. 上述标记将组件扫描到容器后,id属性默认是类名首字母小写。如果需要自定义id值,可以使用@Repository("自定义id值"),其他注解也同理。
  2. 类的命名和变量的命名要规范!首字母大写,第二个字母要小写!否则在使用框架时会有冲突或无法识别,如类名为JDBCCostDAO时无法识别它的id值:jDBCCostDAO,此时以它的类名作为id值却可识别:JDBCCostDAO。
  3. 默认采用singleton模式创建Bean对象,如果需要改变,可以使用

@Scope("prototype")定义。

  1. lazy-init="true"属性只能在<beans>根元素定义了,没有对应的注解。

step3:创建TestAnnotation类,用于测试注解

@Test     //组件扫描

public void test1(){        String conf="/applicationContext.xml";

       ApplicationContext ac=new ClassPathXmlApplicationContext(conf);

       //获取扫描到容器的Bean对象

       CostDAO costDAO=(CostDAO)ac.getBean("jdbcCostDao");

       costDAO.delete();//组件扫描,默认的id为类名首字母小写!且默认单例模式   }

7.3注入注解标记使用方法

如果容器中两个符合要求可被注入同一个组件的Bean对象,可以采用下面注解标记:

1)@Resource,默认按类型匹配注入(JDK自带的)。若有多个符合要求的类型,则报错:匹配不唯一,那么就需要采取按名称注入的方式,它的使用格式为:

                    @Resource(name="需要注入的Bean对象id值")。

2)@Autowired,默认按类型匹配注入(Spring提供的)。若有多个符合要求的类型,则采取按名称注入的方式,它的使用格式为:

                    @Autowired

                    @Qualifier("需要注入的Bean对象id值")

  1. 注意事项:注入标记在成员变量定义前,但@Resource也可以在set方法前使用!

3)案例:id为hibernateCostDao的Bean对象和id为costDao的Bean对象,都符合CostDAO接口,在CostAction组件中注入,那么此时将会报错:匹配不唯一。解决如下:

step1:修改CostActin,添加注入标记

@Controller("costAction")

@Scope("prototype")

public class CostAction {

       //@Resource//将costDao注入,按类型匹配注入,JDK自带的

       //@Autowired//将costDao注入,按类型匹配注入,Spring提供的

       //@Resource(name="hibernateCostDao")//当有多个符合要求的类型,则按名称注入

       @Autowired

       @Qualifier("hibernateCostDao")//当有多个符合要求的类型,则按名称注入

       private CostDAO costDAO;

       public void setCostDAO(CostDAO costDAO) {  this.costDAO = costDAO;     }

      ……       ……                                                                                                  }

step2:在TestAnnotation类,添加方法测试注入标记

@Test     //注入标记测试

public void test2(){        String conf="/applicationContext.xml";

       ApplicationContext ac=new ClassPathXmlApplicationContext(conf);

       CostAction costAction=(CostAction)ac.getBean("costAction");

       costAction.execute();                                                                                         }

step3:可正常执行,如果没写注入标记则报错:NullPointerException

7.4 AOP注解标记使用方法

step1:在applicationContext.xml配置文件中开启AOP注解

                    <aop:aspectj-autoproxy /><!--之前的配置可都删除,只留根元素-->

step2:在方面组件中,使用下面注解标记:

1)首先使用@Component将组件扫描到Spring容器。

2)然后使用@Aspect将组件定义为方面组件。

3)之后定义一个空方法(方法名随便起)在方法前使用@Pointcut定义切入点表达式。

4)最后在方面组件的处理方法前使用@Around、@Before、@AfterReturning、@AfterThrowing、@After

例如:修改5.7案例step4中的LoggerBean类

@Component//将组件扫描到Spring容器

@Aspect//将该组件定义为方面组件

public class LoggerBean {

       //定义切入点

       @Pointcut("within(org.tarena.action..*)")

       public void mypoint(){}//主要目的是使用@Pointcut标记,id则为它的方法名mypoint

       //采用环绕通知

       @Around("mypoint()")//方法即为下面的方法名

       public Object logger(ProceedingJoinPoint pjp) throws Throwable{

       //……方法体内容没变……                                                          }                   }

  1. 注意事项:@Pointcut注解在JDK1.7中不能识别,只能把切入点表达式写在通知中:

@Around("within(org.tarena.action..*)")。而此用法JDK1.6也支持。

step3:再次执行3.3案例step3,则也可正常执行

step4:把6.3案例step2中的ExceptionBean修改为使用AOP注解

@Component//将组件扫描到Spring容器

@Aspect//将该组件定义为方面组件

public class ExceptionBean {

       Logger logger=Logger.getLogger(Exception.class);

       @Pointcut("within(org.tarena.action..*)")

       public void mypoint(){}

       @AfterThrowing(pointcut="mypoint()",throwing="ex")//方法名即为下面方法的名字

       public void exec(Exception ex){    //……方法体内容没变……         }                   }

step5:执行6.3案例step3,则正常执行,控制台显示空指针异常,异常信息也被写入HTML文件。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值