使用注解配置Beanjava
第一件要作的事情就是,添加spring-aop.jar包到项目中。spring
Spring推荐使用4个注解来描述类:express
@Component:组件less
@Repository:持久化层ide
@Service:业务层函数
@Controller:控制器层测试
建立一个user的持久层、业务层和控制器层,并使用注解进行依赖注入:ui
@Component public class TestObject { } // 创建一个组件。
public interface UserRepository { void save(); } // 创建一个持久化层的接口。
@Repository("userRepository") public class UserRepositoryImpl implements UserRepository { @Override public void save() { System.out.println("User Repository Save..."); } } // 持久化接口的实现类,指定@Repoitory注解。
@Repository("userRepository"):@Repository能够添加一个Name参数,意思<bean id="..." />同样。spa
@Service public class UserService { public void add() { System.out.println("user service add..."); } } // 业务层的代码。
@Controller public class UserController { public void execute(){ System.out.println("user controller execute..."); } } // 控制器层代码。
使用context标签来添加配置扫描器:.net
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd"> <!-- 指定spring IOC扫描的package --> <context:component-scan base-package="cn.net.bysoft.lesson6"> </context:component-scan> </beans>
context:component-scan的base-package属性用来告诉扫描器,扫描哪一个包里的文件,能够使用*通配符:
<context:component-scan base-package="cn.net.bysoft.*">
编写一段测试代码:
getBean的参数,默认为类的全名,但首字母小写。但是若是在注解中写了别名,就须要用别名来getBean,好比上面的userRepositoryImpl类。
context:component-scan还能够对扫描的包进行细致的过滤。
能够在元素中加入context:exclude-filter和context:include-filter,前者是排除要扫描的包中的某某某,后者是包含要扫描的包中的某某某,作一个例子使用一下。
上面的4个对象都在cn.net.bysoft.lesson6这个包中,但若是想排除掉TestObject该怎么作呢?以下:
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Component"/>
上面这段代码表明移除全部的@Component注解。
若是有多个类被@Component注解所描述,不想一次都排除掉,能够修改type="assignable",在expression处填写全类名:
<context:exclude-filter type="assignable" expression="cn.net.bysoft.lesson6.TestObject"/>
包含的用法与排除是同样的,可是有一个细节须要注意,就是context:component-scan元素的use-default-filters属性,这个属性是默认的扫描器过滤器是否启动,模式是等于true的,若是须要用context:include-filter,须要将这个属性设置为false:
<context:component-scan base-package="cn.net.bysoft.lesson6" use-default-filters="false"> <context:include-filter type="assignable" expression="cn.net.bysoft.lesson6.TestObject"/> </context:component-scan>
使用注解配置Bean之间的依赖注入
一般,咱们作一个对象的CRUD,都是在Controller层调用Service层的方法,在Service层调用Dao层的方法,那么模拟这个作法,对上面的代码进行修改,模拟类之间的引用:
@Controller public class UserController { @Autowired private UserService userService; public void execute(){ System.out.println("user controller execute..."); userService.add(); } }
设置bean以前的引用,使用@Autowired(自动装配)注解进行描述,Spring会去匹配类型兼容的bean,能够用来描述字段、构造函数和setter方法。把接下来的代码补全:
@Service public class UserService { @Autowired private UserRepository userRepository; public void add() { System.out.println("user service add..."); userRepository.save(); } }
package cn.net.bysoft.lesson6; import org.springframework.stereotype.Repository; @Repository("userRepository") public class UserRepositoryImpl implements UserRepository { @Override public void save() { System.out.println("User Repository Save..."); } }
结果显示正常。
其中Controller类、Service类和Repository类都被注解描述了,可是若是用@Autowired注解去描述没有被注解描述的类是会报错的,须要在@Autowired中设置required=false。
咱们把以前的TestObject类的注解去掉:
package cn.net.bysoft.lesson6; public class TestObject { }
而后在Controller类中使用它,运行程序:
@Controller public class UserController { @Autowired private UserService userServicea; @Autowired() private TestObject testObject; public void execute(){ System.out.println("user controller execute..."); userServicea.add(); System.out.println("打印testObject: " + testObject); } }
报错,不能自动装载字段,修改一下注释:
@Autowired(required=false) private TestObject testObject;
再也不报错了,容许描述的字段为null。
下面的问题,若是在注解中,一个接口被多个类实现,那么自动装配应该去装配哪一个类呢,好比上面的代码中,咱们的UserRepository是一个Interface,被UserRepositoryImpl实现,如今,我在建立一个类实现UserRepository:
@Repository() public class UserRedisRepositoryImpl implements UserRepository { @Override public void save() { System.out.println("User Redis Repository Save..."); } }
而后删除掉UserRepositoryImpl的别名,把@Repository("userRepository")改为@Repository:
@Repository public class UserRepositoryImpl implements UserRepository { @Override public void save() { System.out.println("User Repository Save..."); } }
在进行测试,结果发生了异常:
有几种方式解决,第一个是为其中的某一个类设置@Repository("userRepository"),还能够使用@Qualifier("userRedisRepositoryImpl")来在声明字段时装配指定类型的
@Service public class UserService { @Autowired @Qualifier("userRedisRepositoryImpl") private UserRepository userRepository; public void add() { System.out.println("user service add..."); userRepository.save(); } }
泛型的依赖注入
package cn.net.bysoft.lesson6; import org.springframework.beans.factory.annotation.Autowired; public class BaseService<T> { @Autowired protected BaseRepository<T> baseRepository; public void add(T t) { System.out.println("add..."); baseRepository.save(t); } }
package cn.net.bysoft.lesson6; public class BaseRepository<T> { public void save(T t) { System.out.println(t.getClass() + " save..."); } }
public class Dept {}
public class Role {}
@Service public class DeptService extends BaseService<Dept> { }
@Repository public class DeptRepository extends BaseRepository<Dept> { }
@Service public class RoleServiceextends BaseService<Role> {}
@Repository public class RoleRepository extends BaseRepository<Role> {}
先粘贴出来了八个类,第一个类是泛型Service,第二个类是泛型Repository,第三个和第四个类是两个实体类,第五个第六个是Dept的业务类与持久化类,最后两个是Role的业务类与持久化类。
能够看到,除了两个Base类以外,与以前的配置是同样的,关键在于Base类的配置。
Base类不须要对类进行注解,由于它是用来被继承的,因此由继承它的子类使用类注解。
只须要对引用的类进行@Autowired描述便可,测试一下:
以上,就是使用注解描述bean的基本内容。