Spring注解方式实现IOC和DI
1.Spring注解
Spring除了默认的使用xml配置<bean>标签的方式实现配置外,也可以通过注解的方式来实现配置,这种方式效率更高,配置信息清晰,代码在哪对应的配置也在哪儿。
所谓注解就是程序看的提示信息,很多时候都用来作为轻量级配置方式
Spring注解方式实现IOC
a. 导入开发jar包
b. 编写配置文件,并导入context约束
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<context:component-scan base-package="cn.tedu"></context:component-scan>
<context:annotation-config></context:annotation-config>
</beans>
c. 开启包扫描
<context:component-scan base-package="cn.tedu"></context:component-scan>
d. 使用注解注册bean
在配置的包中的额类上使用@Component注解,这个类会自动被注册为bean,使用当前类的class为的class,默认情况下判断类名的第二字母,如果是大写,首字母不变作为id,如果第二个字母是小写,首字母就是小写,默认作为id,也可以自己指定id
e. 可以使bean类实现BeanNameAware接口,并实现其中setBeanName
方法, spring容器会在初始化bean时,调用此方法告知当前bean的id。通过这个方式可以获取 bean的id信息。
@Component("person")//指定标签id不指定类名的首字母小写
public class Person implements BeanNameAware {
@Override
public void setBeanName(String name) {
System.out.println("==="+this.getClass().getName()+"==="+name);
}
}
f. 注解方式实现工厂注册bean
@Component
public class DogFactory {
@Bean//可以自己指定id,也可以默认getInstance
public Dog getInstance(){
return new Dog("小黑");
}
}
Spring注解方式实现DI
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.2.xsd
">
<context:component-scan base-package="cn.tedu.domain"></context:component-scan>
<!--开启注解方式的DI-->
<context:annotation-config></context:annotation-config>
<context:property-placeholder location="my.properties"></context:property-placeholder>
<util:list id="list">
<value>aaa</value>
<value>bbb</value>
<value>ccc</value>
</util:list>
<util:set id="set">
<value>111</value>
<value>222</value>
<value>333</value>
</util:set>
<util:map id="map">
<entry key="k1" value="v1"></entry>
</util:map>
<util:properties id="properties">
<prop key="1">小</prop>
</util:properties>
</beans>
在类的属性中通过@Value注入赋值
@Component
public class Hero {
//@Value("亚索")
@Value("${name}")
private String name;
//@Value("13")
@Value("${age}")
private int age;
@Value("#{@list}")
private List<String> list;
@Value("#{@set}")
private Set<String> set;
@Value("#{@map}")
private Map<String,String> map;
@Value("#{@properties}")
private Properties props;
@Override
public String toString() {
return "Hero{" +
"name='" + name + '\'' +
", age=" + age +
", list=" + list +
", set=" + set +
", map=" + map +
", props=" + props +
'}';
}
}
f.使用注解注入自定义bean类型数据
在bean中的属性上通过@Autowired实现自定义bean类型的属性注入代码
@Component
public class Hero {
@Value("亚索")
private String name;
@Value("10")
private int age;
@Autowired
@Qualifier("JMDog")//一旦配置了@Qualifier("JMDog")会按照指定id注入,找到注入,找不到就抛出异常
//@Resource(name = "JMDog") Java提供的不是Spring提供的,基本不用
private Dog dog;
@Override
public String toString() {
return "Hero{" +
"name='" + name + '\'' +
", age=" + age +
", dog=" + dog +
'}';
}
}
当Spring容器解析到@Component注解时,创建当前类的bean在Spring容器中进行管理,在创建bean的过程中发现了@Autowired注解,会根据当前bean的类型,寻找Spring中是否存在该类型的bean,如果唯一的bean,直接注入,如果有多个根据id判断,如果有注入,如果没有抛出异常 其次,可以额外配置@Qualifier(“”)注解强制要求按照id进行寻找,找到就注入,找不到就抛出异常,注意@Autowired&@Qualifier(“”)需要配合使用
其他注解
- @Scope(value=“prototype”)
配置修饰类是单例还是多例,Spring默认是单例
//配置bean为多例
@Component
@Scope("prototype")
public class Person {
}
- @Lazy
配置修饰的类的bean采用懒加载机制
Spring默认在初始化时就通过反射创建对象,并且以键值对的形式存入Spring容器中的Map集合中,在类上配置懒加载的注释,可以在对象使用时再创建,避免内存的浪费
@Component
@Lazy//懒加载
public class Person2 {
public Person2() {
System.out.println("person2...init");
}
}
- @PostConstruct
在bean对应的类中 修饰某个方法 将该方法声明为初始化方法,对象创建之后立即执 行。
@PostConstruct
public void initConn(){
System.out.println("初始化数据库连接");
}
- @PreDestroy
在bean对应的类中 修饰某个方法 将该方法声明为销毁的方法,对象销毁之前调用的方 法。
@PreDestroy
public void destroyConn(){
System.out.println("销毁数据库连接");
}
- @Controller @Service @Repository @Component
这四个注解的功能是完全相同的,都是用来修饰类,将雷声名为Spring管理的bean的
@Component 一般认为是通用的注解
@Controller 用在软件分层的控制层,一般用在web层上
@Service用在业务访问层,service层
@Repository用在数据访问层(Dao层)
利用Spring IOC DI 实现软件分层解耦
- 软件分层思想回顾
在软件领域有MVC软件设计思想,指导着软件开发过程。在javaee开发领域,javaee 的经典三层架构MVC设计思想的经典应用。而在软件设计思想中,追求的是"高内聚 低 耦合"的目标,利用Spring的IOC 和 DI 可以非常方便的实现这个需求。
//创建不同类的数据的类型实现userDao接口
@Repository("userDao")
public class OracleUserDao implements UserDao{
@Override
public void addUser() {
System.out.println(this+"正在向数据库添加用户");
}
}
@Repository
public class MySqlUserDao implements UserDao {
@Override
public void addUser() {
System.out.println(this+"正在添加用户");
}
}
public interface UserDao {
public void addUser();
}
//service层
@Service
public class UserServiceImpl implements UserService {
@Autowired
UserDao userDao = null;
@Override
public void regist() {
userDao.addUser();
}
}
public interface UserService {
public void regist();
}
//web层
@Controller
public class RegistServlet {
@Autowired
private UserService service = null;
public void regist() {
service.regist();
}
}