9 Spring基本注解编程
环境配置:在进行注解的使用之前我们需要在配置文件中加入
<context:component-scan base-package="#包的全限命名"/>
开发目录
1.创建对象相关@Component
基本功能
用于替代配置文件中的
例如:我们原来创建对象的方式是这个样子
<bean id="#ID" class="#类名的全限命名"/>
现在只需要在需要创建的类上面加入@Component
@Component
public class User {
xxxx
}
(重要)我们就直接可以在工厂使用类名的首字母小写作为ID创建出来对象
指定标签
我们可在括号中给它标注需要的ID例如:
@Component("user1")
我们就把它ID改为了user1
覆盖标签
我们觉得不满意,可以在配置文件中进行覆盖处理,但是我们需要让id和注解的id保持一致,否则,Spring会创建同名不同类的对象,也就起不到覆盖的作用
例如:我改了上面对应注解的类,并改了创建这个类时的一些属性
<bean id="user" class="#类名的全限命名" scope="prototype"/>
其他相同功能的注解
和@Component功能一致,但是是为了专门标注执行不同业务的类
- @Controller 标注Controller
- @Repository 标注 DAO
- @Repository 标注 Service
但是在和Mybaits 整合的时候我们不用@Repository 以及@Component
2.@Scope
传统开发中我们指定何时创建对像,在标签中指定scope
在注解开发中使用@Scope("prototype")或者@Scope("singleton")都是一样的
例如:对象将在使用时创建
@Scope("prototype")
public class User {
xxxx
}
3.@Lazy,@PostConstruct,@PreDestroy
推后(延迟)创建对象,在工厂创建时如果没有指定延迟创建,那么此对象的无参构造方法和初始化方法都会执行
@Lazy指定这个类是否延迟加载,在使用时加载
@PostConstruct 指定这个方法为初始化方法
@PreDestroy指定这个方法为销毁方法
例如:
@Lazy(true)
public class UserServiceImpl implements UserService {
//无参构造方法
public UserServiceImpl() {
System.out.println("UserServiceImpl.UserServiceImpl");
}
//初始化方法
@PostConstruct
public void MyinitMehtond(){
System.out.println("UserServiceImpl.MyinitMehtond");
}
//销毁方法
@PreDestroy
public void MyDestory(){
System.out.println("UserServiceImpl.MyDestory");
}
}
使用了@Lazy(true)那么在创建工厂时它被稍后使用时加载
例如创建工厂代码
public void test2(){
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("ApplicationContext-Annotation.xml");
//UserService service= (UserService) context.getBean("userServiceImpl");
}
运行它发现没任何反应
我们使用它取消使用它的注释,可以看到这个方法被加载了包括初始化方法
那么@PreDestroy是在工厂关闭时启动销毁方法,销毁工厂context.close();
可以看到销毁方法被调用
4.注入的相关注解@Autowired,@PropertySource,@Value
自定义类型
@Autowired将为放置位置的变量进行注入
例如:我们有了一个DAO的对象,要使用它的save方法,我们得首先创建他
@Repository
public class UserDAOImpl implements UserDAO {
@Override
public void save() {
System.out.println("UserDAOImpl.save");
}
}
在Service层中调用它就得把他创建的对象赋值给对应方法
@Service
public class UserServiceImpl implements UserService {
//声明的DAO变量
//方式一
private UserDAO userDAO;
public UserDAO getUserDAO() {
System.out.println("UserServiceImpl.getUserDAO");
return userDAO;
}
//提供SET和GET方法
//方式二
//@Autowired
public void setUserDAO(UserDAO userDAO) {
System.out.println("UserServiceImpl.setUserDAO");
this.userDAO = userDAO;
}
//调用DAO方法
@Override
public void register() {
System.out.println("UserServiceImpl.register");
userDAO.save();
}
@Override
public void login(String name, String password) {
System.out.println("UserServiceImpl.login");
}
方式一:在成员变量上注解
Spring会自动的通过反射为对应的变量进行注入[推荐方式]
方式二:在set方法上面进行注解
Spring会自动的寻找与之对应的成员变量(也就是上面声明的DAO变量)的相同类型或者子类
JDK类型
这个方法比较麻烦、
开发步骤:
- 在properties文件中设置键值对
- 在工厂或者注解读取配置文件
- 写注解
-
在properties文件中设置键值对
例如我要为实体类的两个变量注入两个值
public class User implements Serializable { private String name; private String password; //为其提供SET/GET方法这里就不写出来了,节约篇幅 }
在配置文件DataBase.properties中如下书写
JDBC_User=root JDBC_Password=atgxstuSf2e
-
在工厂或者注解读取配置文件
在类上使用@PropertySource注解表明配置文件
@PropertySource("classpath:/DataBase.properties") public class User implements Serializable { private String name; private String password; }
-
写注解
格式为@Value("${键值}")
@PropertySource("classpath:/DataBase.properties") public class User implements Serializable { @Value("${JDBC_User}") private String name; @Value("${JDBC_Password}") private String password; }
注意点:
这个注入方法不能用在静态成员变量以及不可以注入集合等复杂类型,使用还是比较繁琐
5.注解扫描
在上面的环境配置配置了Spring需要扫描的包的注解,那么用起来必须有局限性,Spring还提供了自定义的对注解扫描的方式
总体来说,Spring为我们提供了两种自定义注解扫描方式
- 包含形式
- 排除形式
包含形式和排除形式都大同小异
大同在有相同的扫描方法和对扫描方法的配置
- assignable 基于特定类型的方式
- aspectj 基于切入点表达式的方式
- annotation 基于注解的方式
- custom 用于Spring框架底层开发(没到那个水平)
- regex 基于正则表达式的方式(和切入点表达式比起来肯定切入点表达式好用)
1.排除形式
配置形式
<context:component-scan base-package="#某个包">
<context:exclude-filter type="#扫描方法" expression="#扫描方法的配置"/>
</context:component-scan>
一,assignable
我把org.AnnotationProgramming.Entity.User这个类排除了,不作为扫描的类,所以也就不会被Spring创建出来(事先加入了@Component注解)
<context:exclude-filter type="assignable" expression="org.AnnotationProgramming.Entity.User"/>
测试代码:
getBeanDefinitionNames是Spring创建的对象名字
public void test3(){
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("ApplicationContext-Annotation.xml");
String[]strings=context.getBeanDefinitionNames();
for (String string : strings) {
System.out.println("string = " + string);
}
}
运行结果:
可以看到User类并没有被创建出来说明被排除了
二,aspectj
排除了org.AnnotationProgramming.DAO这个包下的所有类
具体演示就不弄了
<context:exclude-filter type="aspectj" expression="org.AnnotationProgramming.DAO..*"/>
三,annotation
排除了Repository这个注解,需要填写注解的全限命名
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
四,custom和regex使用频率极低就不介绍
2.包含属性
所有的内容和排除一致,只不过扫描的类从排除变为扫描了
3.混合使用
包含和排除属性可以任意搭配,不过排除之后不可以使用包含,注意选择逻辑,自由搭配
6.对注解开发的其他注意事项
1.注解配置的类和配置文件是互通的,也就是说注解中设置的ID在配置文件中可以使用
2.使用注解的时机:多在自己开发程序时候,也就是自己写的类,但是在使用其他人提供的类,比如SqlsessionFactoryBean还是得在配置文件中进行配置,所以开发是混合开发
还有更多高级注解(Spring3以后)在下一篇笔记将会提到,这些都属于基础注解,也就是早期Spring提供的注解