spring注解
2016-07-04 00:54
351 查看
注解的使用,首先编写一个注册文件Configure.java,并用@Configuration注解,然后使用注解容器类加载bean即可.
@ComponentScan,使用在配置类上,用于自动扫描bean.
@ComponentScan.Filter,用于配置扫描过滤规则
属性如下
@Component,标记一个类为组件类,扫描时自动创建bean,创建顺序如下:
若该类有一个@AutoWired注解的构造器,则使用该构造器实例化,若没有则使用空白构造器实例化.(两者皆无则报错)
先注入注解在实例域上的@AutoWired/@Value.
再解析注解在实例方法上的@AutoWired/@Value
@Bean用在配置类的方法中,表示该方法会返回一个bean,beanId与方法名同,用于显式地配置一个bean.
@Import,用于导入另外一个配置类的信息到当前配置类.
@ImportResource,用于导入配置文件到当前配置类.
@Profile,用于配置不同环境下生成不同的bean.
可以用在@Component注解的自动扫描组件和@Bean注解的(方法)显式组件中,如果用在配置类上则表示所有经由该配置类产生的bean(显式/组件扫描)都有profile控制.
@Conditional,配置条件bean,该注解需要传入一组Condition实现类,只有指定的所有Condition的实现类中的matches返回true,bean才能被创建.
@Primary标记一个bean为主候选bean,用于解决自动注入的冲突.
@Qualifier,用于缩小候选bean范围.
@Scope,用于控制bean的生成模式
以下为proxyMode配置后的工作模式,可以看到通过注入一个动态代理,可以在一个单例中调用不同的注入对象。
@PropertySource(“classpath:/com/soundsystem/app.properties”)+Environment用于加载properties文件的值.
@Value+PropertySourcesPlaceholderConfigurer实现属性占位符
SpEL,以#{…}为标志,内部为方法体.
SpEL支持的操作
@Configuration @ComponentScan(basePackages = {"music"},excludeFilters = {@ComponentScan.Filter(value = MF.class)}) public class Configure { @Bean public A excplicateBean(){ return new A(); } } //使用 AnnotationConfigApplicationContext acfc = new AnnotationConfigApplicationContext(Configure.class); //web使用AnnotationConfigWebApplicationContext
@ComponentScan,使用在配置类上,用于自动扫描bean.
//基本属性 value/basePackages:指定一组要扫描的包,将扫描这些包及其子包下的文件.(默认基包为配置类所在的包) classes:直接指定扫描的一些类,这些类所在的包及其子包也会被扫描. nameGenerator:指定一个默认扫描组件的命名类,默认命名使用组件类名第一个字小写. excludeFilters:需要一组@ComponentScan.Filter的注解配置,每个@Filter可以配置一组过滤规则,多个@Filter可以基于正则/注解/具体类配置不同的过滤规则. includeFilters:反上.
@ComponentScan.Filter,用于配置扫描过滤规则
属性如下
type | value/classes | pattern |
---|---|---|
FilterType.ANNOTATION(默认) | 一组注解,命中所有使用该注解的类,{MyAnno.class} | - |
FilterType.ASSIGNABLE_TYPE | 一组具体类 | - |
FilterType.ASPECTJ | - | 一组表达式,使用Aspectj表达式命中类 |
FilterType.REGEX | - | 一组表达式,使用正则命中类 |
FilterType.CUSTOM | 自定义的TypeFilter. | - |
若该类有一个@AutoWired注解的构造器,则使用该构造器实例化,若没有则使用空白构造器实例化.(两者皆无则报错)
先注入注解在实例域上的@AutoWired/@Value.
再解析注解在实例方法上的@AutoWired/@Value
@Bean用在配置类的方法中,表示该方法会返回一个bean,beanId与方法名同,用于显式地配置一个bean.
@Configuration @ComponentScan public class Configure { @Bean //@Scope("prototype")未设置prototype则该方法会一直返回同一个单例 //singleton模式则第二次调用时直接返回已创建对象,不再执行new/set等方法 public A a(){ A a = new A(); a.setX(10); return a; } //相当于引用了a()产生的对象,a()在singleton模式下只返回单例 @Bean public B b1(){ return new B(a()); } //可以把其他bean放在参数中自动注入,好处是注入的bean可以来自xml配置/自动扫描 @Bean public B b2(A a){ return new B(a); } } @Bean创建bean的过程如下: 1. 调用注解的方法产生一个实例对象,如果该方法有参数,则对参数注入. 2. 如果返回对象的对应类的某些实例域上有@Value/@AutoWired注解,则对返回对象的这些实例域进行注入. 3. 如果返回对象的对应类的某些方法上有@Value/@AutoWired注解,则对返回对象的这些方法进行注入.
@Import,用于导入另外一个配置类的信息到当前配置类.
@ImportResource,用于导入配置文件到当前配置类.
@Configuration @Import(Part1Config.class) @ImportResource("classpath:cd-config.xml") public class RootConfig{ } //tips,如果需要导入一个java config到xml配置文件中,直接使用bean即可 //<bean class="PartOneConfig.class"/>
@Profile,用于配置不同环境下生成不同的bean.
可以用在@Component注解的自动扫描组件和@Bean注解的(方法)显式组件中,如果用在配置类上则表示所有经由该配置类产生的bean(显式/组件扫描)都有profile控制.
@Configuration public class Configure { //未配置profile则在所有环境下都会被创建 @Bean public ComponentDisc componentDisc(){ System.out.println("create bean cdisk"); return new SgtPers(); } @Bean //该bean只有在名为dev的profile激活时才能被创建 @Profile("dev") public DisckPlayer disckPlayer(){ DisckPlayer disckPlayer = new DisckPlayer(); disckPlayer.setDisc(componentDisc()); disckPlayer.setPlayTime(10); return disckPlayer; } @Bean //该bean只有在名为test的profile激活时才能被创建 @Profile("test") public DisckPlayer disckPlayer1(){ DisckPlayer disckPlayer = new DisckPlayer(); disckPlayer.setDisc(componentDisc()); disckPlayer.setPlayTime(12); return disckPlayer; } } 通过两个参数可以选择激活哪些profiles: spring.profiles.active spring.profiles.default ;active未配置时生效 当两个参数都没有配置时,则所有的profile限定bean都不被创建. 参数可以在以下位置配置: As initialization parameters on DispatcherServlet As context parameters of a web application As JNDI entries As environment variables As JVM system properties Using the @ActiveProfiles annotation on an integration test class //在web.xml中配置 <?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/root-context.xml</param-value> </context-param> <context-param> <param-name>spring.profiles.default</param-name> <param-value>dev</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <servlet> <servlet-name>appServlet</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <init-param> <param-name>spring.profiles.default</param-name> <param-value>dev</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>appServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
@Conditional,配置条件bean,该注解需要传入一组Condition实现类,只有指定的所有Condition的实现类中的matches返回true,bean才能被创建.
tips:4.0以后@Profile使用@Conditional实现,对应的Condition实现类为ProfileCondition 以下为ProfileCondition源码 class ProfileCondition implements Condition { //所有的Condition实现类都能获得ConditionContext与AnnotatedTypeMetadata @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { if (context.getEnvironment() != null) { MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName()); if (attrs != null) { for (Object value : attrs.get("value")) { if (context.getEnvironment().acceptsProfiles(((String[]) value))) { return true; } } return false; } } return true; } }
@Primary标记一个bean为主候选bean,用于解决自动注入的冲突.
@AutoWired是通过类型进行注入的,当同一个接口有多个实现,且都注册为bean时, spring无法选择哪个候选bean用于注入,此时通过将bean注解为@Primary,则注入 有冲突时优先选择主候选bean.
@Qualifier,用于缩小候选bean范围.
tips: @Qualifier("q")用于bean声明处(@Bean/@Component)时,表示限定该bean的选择范围为q. @Qualifier用于注入点(@Autowired)时,表示选择注解为@Qualifier("q")的bean进行注入或者使用id为q的bean注入. 可以同时使用多个@Qualifier,进行更为详细的特征限定. @Bean @Qualifier("cold") public Dessert iceCream() { return new IceCream(); } //选择候选名为cold的可能候选bean进行注入 @Autowired @Qualifier("cold") public void setDessert(Dessert dessert) { this.dessert = dessert; } //由于java不允许在一个位置重复使用一个注解,所以当需要使用多个特征进行限定时则需要自定义注解。 @Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) //Spring扫描注解时,会解析注解上的注解并应用 @Qualifier @interface Cold{} @Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Qualifier @interface Soft{} 使用时可以一起使用,进行多特征限定 @Bean @Cold @Soft public Dessert iceCream() { return new IceCream(); }
@Scope,用于控制bean的生成模式
属性 | 作用 |
---|---|
scopeName/value | singleton:单例模式。prototype:每次调用生成新对象。session:用于web,为每个session生成一个实例。request:用于web,为每个request生成实例 |
proxyMode | ScopeProxyMode.INTERFACES:基于接口使用jdk动态代理,当代理的类为借口时使用。ScopeProxyMode.TARGET_CLASS:基于CGLib的动态代理,当代理的类为具体类时使用 |
代理模式的作用,考虑以下情况 @Bean @Scope("prototype") public A a(){ return new A(); } @Bean @Scope("singleton") public B b(){ return new B(a()); } 此时由于bean-b为单例模式,所以只创建一次,只调用一次 a(),所以每次调用b.a.action(),实际调用的是同一个 bean-a,如果希望每次调用b.a.action()都能使用新创建 的A对象,那么必须配置一个proxyMode属性,它会创建一个 A的代理类,当具体调用A类方法时,再调用getBean("a") 从Spring容器中获得一个新创建的A,然后调用. 最常用的情况是在scopeName为request/session,因为 service层一般是单例,而request/session域的bean- rs是根据session/request创建、获取的,所以在启动时往 service中注入rs是不可能的,只能先创建一个动态代 理,当具体连接到来,再通过动态代理调用getBean("class-sessionId")获得具 体不同的实例对象并调用具体方法。 总而言之,proxyMode属性设置后,会延迟到属性/方法的调用时才会真正的去加载一 个bean,每次调用都要重新加载,对于prototype,每次都返回新对象,request /session则返回对应的bean.
以下为proxyMode配置后的工作模式,可以看到通过注入一个动态代理,可以在一个单例中调用不同的注入对象。
@PropertySource(“classpath:/com/soundsystem/app.properties”)+Environment用于加载properties文件的值.
tips:Environment除了可以使用getProperties加载资源还有getActivyProfiles等用于检测profiles的方法. @PropertySource("classpath:/com/soundsystem/app.properties") @Configuration class Configure{ @Autowired Environment env; @Bean A a(){ return new A(env.getProperties("key","defaultValue")); } }
@Value+PropertySourcesPlaceholderConfigurer实现属性占位符
//启用属性占位符 @Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer(){ return new PropertySourcesPlaceholderConfigurer(); } class A{ //使用@Value("${key}")获取属性,并设置到属性上 A(@Value("${key}")String x){ this.x = x; } }
SpEL,以#{…}为标志,内部为方法体.
class A{ //加载一个属性,与属性占位符同效果 @Value("#{systemProperties['key']}") private String x; //通过T操作符使用静态方法与静态域 @Value("T(System).currentTimeMillis()" private long time; //直接使用另外一个bean的方法/属性 @Value("b.getPoint()") private String point; //?.操作,只有在左部非空才往后调用,否则返回null,保证不会有NPE. @Value("b?.getPoint()?.toUpperCase()") private String dot; //+操作 @Value("p.firstName+'.'+p.sencodName") //正则判断 @Value("p.email matches '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.com'") //集合操作,取集合/数组中的第n个元素 @Value("singer.songs[1]") //.?[expression]根据expression的返回值过滤集合 @Value("singer.songs.?[name.contains('love')]") //.^[expression],选择集合中满足expression的第一个元素 @Value("singer.songs.^[getName() matches '*love*']") //.$[expression],选择集合中满足expression的最后一个元素 @Value("singer.songs.$[getName() matches '*love*']") //.![expression],根据expression的返回值形成新集合 @Value("singer.songs.![getName()]") }
SpEL支持的操作
Operator type | Operators |
---|---|
Arithmetic | +, -, *, /, %, ^ |
Comparison | <, lt, >, gt, ==, eq, <=, le, >=, ge |
Logical | and, or, not, | |
Conditional | ?: (ternary), ?: (Elvis) |
Regular expression | matches |
相关文章推荐
- 一个jar包里的网站
- 一个jar包里的网站之文件上传
- 一个jar包里的网站之返回对媒体类型
- Spring和ThreadLocal
- Spring Boot 开发微服务
- Spring AOP动态代理-切面
- Spring整合Quartz(JobDetailBean方式)
- Spring整合Quartz(JobDetailBean方式)
- 模拟Spring的简单实现
- Spring整合WebSocket应用示例(上)
- spring+html5实现安全传输随机数字密码键盘
- Spring中属性注入详解
- 监听器获取Spring配置文件的方法
- Java利用Sping框架编写RPC远程过程调用服务的教程
- springmvc 发送ajax出现中文乱码的解决方法汇总
- SpringMVC框架下JQuery传递并解析Json格式的数据是如何实现的
- 详解Java的MyBatis框架和Spring框架的整合运用
- struts2 spring整合fieldError问题
- spring的jdbctemplate的crud的基类dao