使用注解实现 控制反转 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衍生的三个注解
- Spring为了代码的可读性,spring框架又推出了下边三个注解。下边三个注解和第一个注解的作用是完全一样的,就是为了规范。
- @Controller 加到Action类上边,代表这是一个控制器
- @Service 加到Service实现类上边,代表这是一个业务逻辑层的类
- @Repository 加到Dao实现类上边,代表这是操作数据库的
- 注:由于我们现在使用的mybatis框架,所以@Repository注解是不需要使用的
注:如果一个接口有两个或多实现类,使用@Autowired自动装配会报错.
解决方案:使用精准装配
- 例如:
- service起上名字
- 在@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或以上版本
使用步骤:
- 在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>
- 编写额外功能类、添加一些需要增强的方法
@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("最终增强。。。。。。。。。。。。。");
}
}