官网文档
注:自动装配指的是引用对象的自动装配,基本类型还是需要手动设置
<bean id="cat" class="com.chelsea.pojo.Cat" scope="prototype"/>
<bean id="dog" class="com.chelsea.pojo.Dog" scope="prototype"/>
<bean id="user" class="com.chelsea.pojo.Person" scope="prototype" p:name="chelsea" p:cat-ref="cat" p:dog-ref="dog"/>
<bean id="user1" class="com.chelsea.pojo.Person" autowire="byName">
<property name="name" value="chelsea"/>
bean>
<bean id="user2" class="com.chelsea.pojo.Person" autowire="byType">
<property name="name" value="chelsea"/>
bean>
<context:annotation-config/>
在xml文件中开启注释后,就可以在对应的属性上使用注解进行自动装配了
/*使用Autowired自动装配就可以不编写set方法,此注解即可以用到属性上,也可以用到set方法上*/
/*使用Autowired不编写set方法时,前提是这个自动装配的属性在IOC容器中已经配置,且同名*/
@Autowired
private Dog dog;
/*添加参数required=false,表示允许此属性值为null*/
@Autowired(required = false)
/*Autowired通过byName和byType的方式进行自动装配,当两种方法都不可行时,可添加Qualifier注解装配,参数为配置的bean id值*/
//@Qualifier("cat111")
private Cat cat;
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
<context:annotation-config/>
<context:component-scan base-package="com.chelsea.pojo"/>
实体类如下,其他层中还有对应的@Service,@Controller,@Repository等,这几个都是将对应的类配置为Bean。
/*等价于在xml文件中配置的Bean*/
@Component
public class User {
@Value("chelsea")
private String name;
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
import com.chelsea.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/*此类是spring配置类,替代了xml文件,需要添加Configuration注解*/
@Configuration
@ComponentScan("com.chelsea.pojo")
/*引入另一个配置对象*/
@Import(chelseaConfig2.class)
public class chelseaConfig {
/*从上下文中获取bean实例的时候,需要传入方法名称,这样配置后,实体类中的注解才会生效*/
/*就相当于之前写的一个bean标签,方法名就相当于bean标签中的id属性
* 返回值就相当于标签的class属性,表示bean的类型*/
@Bean
public User getUser(){
return new User();
}
}
@Test
public void testGetUser(){
//之前的加载方式
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("userBean.xml");
//现在的加载方式:加载注解上下文驱动
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(chelseaConfig.class);
//从上下文中获取bean
User user = applicationContext.getBean("getUser", User.class);
//进行测试
System.out.println(user.toString());
}
// 房东群体要执行租房子的任务
public interface Rent {
public void rent();
}
//单个房东要租出房子
public class Host implements Rent {
@Override
public void rent() {
System.out.println("房东要租房子");
}
}
//中介说,我帮你租出吧,我还会带人家看房和签合同,省得你麻烦(可以一直嵌套中介)
public class Proxy {
// 能使用组合尽量使用组合 不使用继承
private Host host;
public Proxy() {
}
public Proxy(Host host) {
this.host = host;
}
public void rent(){
kanfang();
host.rent();
qianhetong();
}
//需要给上一层添加任务又不修改上一层时,就使用代理模式,自行添加任务
public void kanfang(){
System.out.println("代理带你去看房");
}
public void qianhetong(){
System.out.println("中介签租赁合同");
}
}
//客户,我来租房子啦,我直接找中介就行
public class client {
public static void main(String[] args) {
//房东要租房子
Host host = new Host();
//代理帮房东租房子,同时代理一般会有一些附属操作
Proxy proxy = new Proxy(host);
//你不用直接面向房东,直接找中介租房即可!
//spring AOP 采用分层的思想,每一层就是在上一层嵌套操作而已,所以使用代理模式
proxy.rent();
}
}
//动态代理生成器,代理接口即可
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的接口
private Object target;
public void setTarget(Object target) {
this.target = target;
}
//生成的到代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
target.getClass().getInterfaces(),this);
}
//处理代理实例 并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log(method.getName());
Object result = method.invoke(target,args);
return result;
}
//假如我的新代理逻辑是要添加日志功能,方法添加如下
public void log(String msg){
System.out.println("[debug] " + msg + "了一个用户");
}
}
// 客户使用动态代理来租房子
public class Client {
public static void main(String[] args) {
//真实角色
UserDaoImpl userDao = new UserDaoImpl();
//代理角色 不存在
ProxyInvocationHandler proxy = new ProxyInvocationHandler();
//设置要代理的对象
proxy.setTarget(userDao);
//动态生成代理类
UserDao daoProxy = (UserDao) proxy.getProxy();
daoProxy.add();
}
}
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.9.4version>
dependency>
<bean id="userService" class="com.chelsea.services.UserServicesImpl"/>
<bean id="log" class="com.chelsea.log.log"/>
<bean id="afterLog" class="com.chelsea.log.AfterLog"/>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.chelsea.services.UserServicesImpl.*(..))"/>
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
aop:config>
<bean id="diyPoint" class="com.chelsea.diy.DiyPointCut"/>
<aop:config>
<aop:aspect ref="diyPoint">
<aop:pointcut id="pointcut" expression="execution(* com.chelsea.services.UserServicesImpl.*(..))"/>
<aop:after method="after" pointcut-ref="pointcut"/>
<aop:before method="before" pointcut-ref="pointcut"/>
aop:aspect>
aop:config>
public class DiyPointCut {
public void after(){
System.out.println("方法已经执行!");
}
public void before(){
System.out.println("准备执行方法!");
}
}
首先打开注解支持,接下来使用注解添加AOP机制
<bean class="com.chelsea.diy.AnnoPointCut" id="annoPointCut"/>
<aop:aspectj-autoproxy/>
首先直接读取此注解,然后添加响应的切入点逻辑,传入上层参数。
@Aspect
public class AnnoPointCut {
@Before("execution(* com.chelsea.services.UserServicesImpl.*(..))")
public void before(){
System.out.println("============== 方法执行前!===============");
}
@After("execution(* com.chelsea.services.UserServicesImpl.*(..))")
public void after(){
System.out.println("============== 方法执行后!===============");
}
@Around("execution(* com.chelsea.services.UserServicesImpl.*(..))")
public void around(ProceedingJoinPoint joinPoint){
System.out.println("环绕前");
//获得签名
Signature signature = joinPoint.getSignature();
System.out.println("signature:"+signature);
//执行方法
Object proceed = null;
try {
proceed = joinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
System.out.println("环绕后");
System.out.println(proceed);
}
}
注:aroud注解优先级高于after等,执行结果如下
环绕前
signature:void com.chelsea.services.UserService.add()
============== 方法执行前!===============
增加了一个用户
============== 方法执行后!===============
环绕后